Commit 94a1346a authored by Rogerborg's avatar Rogerborg

Adding an optional light manager that allows hardware lights to be turned on...

Adding an optional light manager that allows hardware lights to be turned on and off before each scene node is rendered. This can be used to produce "zoned" lighting.

If a light manager is not registered, the existing behaviour (activate the closest lights to the camera) will be retained unchanged.  New example project added to demonstrate the usage, and regression tests and existing samples run.  No regression test for the light manager yet, since I am more interested in not regressing the default behaviour.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2064 dfc29bdd-3216-0410-991c-e03cc46cb475
parent de02b25a
Changes in version 1.6
- 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.
......
# 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
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
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="Irrlicht Example 19 ManagedLights" />
<Option pch_mode="0" />
<Option compiler="gcc" />
<Build>
<Target title="default">
<Option output="..\..\bin\gcc\ManagedLights" prefix_auto="0" extension_auto="1" />
<Option type="1" />
<Option compiler="gcc" />
<Option projectResourceIncludeDirsRelation="1" />
<Compiler>
<Add option="-Wall" />
<Add option="-g" />
</Compiler>
</Target>
</Build>
<VirtualTargets>
<Add alias="All" targets="default;" />
</VirtualTargets>
<Compiler>
<Add option="-Wall" />
<Add option="-g" />
<Add directory="..\..\include" />
</Compiler>
<Linker>
<Add library="Irrlicht" />
<Add directory="..\..\lib\gcc" />
</Linker>
<Unit filename="main.cpp" />
<Extensions>
<code_completion />
<debugger />
</Extensions>
</Project>
</CodeBlocks_project_file>
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "20.ManagedLights", "ManagedLights.vcproj", "{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|Win32.ActiveCfg = Debug|Win32
{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|Win32.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="20.ManagedLights"
ProjectGUID="{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Debug/ManagedLights.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=".\Debug/ManagedLights.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="3079"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="..\..\bin\Win32-VisualStudio\20.ManagedLights.exe"
LinkIncremental="0"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\lib\Win32-visualstudio"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/ManagedLights.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Release/ManagedLights.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=".\Release/ManagedLights.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="3079"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="..\..\bin\Win32-VisualStudio\20.ManagedLights.exe"
LinkIncremental="0"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\lib\Win32-visualstudio"
ProgramDatabaseFile=".\Release/ManagedLights.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="main.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
BasicRuntimeChecks="3"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="20.ManagedLights_vc8"
ProjectGUID="{16007FE2-142B-47F8-93E1-519BA3F39E71}"
RootNamespace="ManagedLights_vc8"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Debug/ManagedLights.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=".\Debug/ManagedLights.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="3079"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="..\..\bin\Win32-VisualStudio\20.ManagedLights.exe"
LinkIncremental="0"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\lib\Win32-visualstudio"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/ManagedLights.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Release/ManagedLights.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=".\Release/ManagedLights.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="3079"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="..\..\bin\Win32-VisualStudio\20.ManagedLights.exe"
LinkIncremental="0"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\lib\Win32-visualstudio"
ProgramDatabaseFile=".\Release/ManagedLights.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="main.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
BasicRuntimeChecks="3"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="20.ManagedLights_vc9"
ProjectGUID="{FE853A36-E0D1-4AC5-A792-B643E70D2953}"
RootNamespace="ManagedLights_vc9"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Debug/ManagedLights.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=".\Debug/ManagedLights.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="3079"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="..\..\bin\Win32-VisualStudio\20.ManagedLights.exe"
LinkIncremental="0"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\lib\Win32-visualstudio"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/ManagedLights.pdb"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Release/ManagedLights.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=".\Release/ManagedLights.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="3079"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="..\..\bin\Win32-VisualStudio\20.ManagedLights.exe"
LinkIncremental="0"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\lib\Win32-visualstudio"
ProgramDatabaseFile=".\Release/ManagedLights.pdb"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="main.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
BasicRuntimeChecks="3"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
[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
// Written by Colin MacDonald
// Copyright (C) 2002-2009 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#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")
/*
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 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.
ISceneManager * SceneManager;
core::array<ILightSceneNode*> * SceneLightList;
E_SCENE_NODE_RENDER_PASS CurrentRenderPass;
ISceneNode * CurrentSceneNode;
public:
CMyLightManager(ISceneManager* sceneManager)
: SceneManager(sceneManager), SceneLightList(0),
CurrentRenderPass(ESNRP_COUNT), CurrentSceneNode(0),
Mode(NO_MANAGEMENT), RequestedMode(NO_MANAGEMENT)
{ }
virtual ~CMyLightManager(void) { }
// The input receiver interface, which just switches light management strategy
bool CMyLightManager::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<ILightSceneNode*> & 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(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(E_SCENE_NODE_RENDER_PASS renderPass)
{
// I only want solid nodes to be lit, so after the solid pass, turn all lights off.
if(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(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(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() != 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<LightDistanceElement> sortingArray;
sortingArray.reallocate(SceneLightList->size());
u32 i;
for(i = 0; i < SceneLightList->size(); ++i)
{
ILightSceneNode* lightNode = (*SceneLightList)[i];
SLight & lightData = lightNode->getLightData();
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)
{
ILightSceneNode* lightNode = (*SceneLightList)[i];
SLight & lightData = lightNode->getLightData();
if(ELT_DIRECTIONAL != lightData.Type)
lightNode->setVisible(false);
}
ISceneNode * parentZone = findZone(node);
if(parentZone)
turnOnZoneLights(parentZone);
}
}
// Called after the specified scene node is rendered
virtual void OnNodePostRender(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
ISceneNode * findZone(ISceneNode * node)
{
if(!node)
return 0;
if(node->getType() == 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(ISceneNode * node)
{
core::list<ISceneNode*> const & children = node->getChildren();
for (core::list<ISceneNode*>::ConstIterator child = children.begin();
child != children.end();
++child)
{
if((*child)->getType() == ESNT_LIGHT)
static_cast<ILightSceneNode*>(*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(ILightSceneNode* n, f64 d)
: node(n), distance(d) { }
ILightSceneNode* 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[])
{
char driverChoice;
if(argumentCount > 1)
driverChoice = argumentValues[1][0];
else
{
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) Burning's Software Renderer\n(otherKey) exit\n\n");
std::cin >> driverChoice;
}
video::E_DRIVER_TYPE driverType;
switch(driverChoice)
{
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_BURNINGSVIDEO; break;
default: return 0;
}
IrrlichtDevice *device = createDevice(driverType, dimension2d<s32>(640, 480), 32,
false, false, false, 0);
if(!device)
return -1;
f32 const lightRadius = 60.f; // Enough to reach the far side of each 'zone'
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
gui::IGUISkin* skin = guienv->getSkin();
if (skin)
{
skin->setColor(EGDC_BUTTON_TEXT, 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<s32>(10,10,200,30));
guienv->addStaticText(L"2 - Closest 3 lights", core::rect<s32>(10,30,200,50));
guienv->addStaticText(L"3 - Lights in zone", core::rect<s32>(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.
ISceneNode * zoneRoot = smgr->addEmptySceneNode();
zoneRoot->setPosition(vector3df(zoneX, zoneY, 0));
// Each zone contains a rotating cube
IMeshSceneNode * node = smgr->addCubeSceneNode(15, zoneRoot);
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.
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);
ILightSceneNode * light = smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), 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);
light = smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), 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);
light = smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), 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, 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;
}
......@@ -42,6 +42,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16.Quake3MapShader_vc8", "1
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "19.MouseAndJoystick_vc8", "19.MouseAndJoystick\MouseAndJoystick_vc8.vcproj", "{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "20.ManagedLights_vc8", "20.ManagedLights\ManagedLights_vc8.vcproj", "{16007FE2-142B-47F8-93E1-519BA3F39E71}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
......@@ -124,6 +126,10 @@ Global
{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
{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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
// Written by Colin MacDonald - all rights assigned to Nikolaus Gebhardt
// Copyright (C) 2008-2009 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;
//! Provides callbacks to when the the scene graph is rendered.
/** ILightManager is an optional manager that the user application can
register in order to receive callbacks as the scene is rendered.
The OnPreRender() callback provides the user application with a list of the
lights in the scene. This list can be stored and used to turn lights
on and off as each scene node is rendered in order to provide per-node
or 'local' lights.
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[in] smgr: the Scene Manager
//! \param[inout] lightLight: the Scene Manager's light list, which the light manager may
//! modify. This reference will remain valid until OnPostRender().
virtual void OnPreRender(core::array<ILightSceneNode*> & 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[in] 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
......@@ -40,6 +40,12 @@ public:
/** \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
......
......@@ -113,6 +113,7 @@ namespace scene
class ISceneNodeFactory;
class ISceneNodeAnimatorFactory;
class ISceneUserDataSerializer;
class ILightManager;
namespace quake3
{
......@@ -1368,6 +1369,11 @@ namespace scene
//! Returns 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 behaviour. */
virtual void setLightManager(ILightManager* lightManager) = 0;
};
......
......@@ -724,9 +724,10 @@ namespace video
//! Deletes all dynamic lights which were previously added with addDynamicLight().
virtual void deleteAllDynamicLights() = 0;
//! Adds a dynamic light.
/** \param light Data specifying the dynamic light. */
virtual void addDynamicLight(const SLight& light) = 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. */
......@@ -742,6 +743,11 @@ namespace video
\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". */
......
......@@ -150,6 +150,7 @@
#include "IWriteFile.h"
#include "IXMLReader.h"
#include "IXMLWriter.h"
#include "ILightManager.h"
#include "Keycodes.h"
#include "line2d.h"
#include "line3d.h"
......
......@@ -1767,11 +1767,8 @@ void CD3D8Driver::deleteAllDynamicLights()
//! adds a dynamic light
void CD3D8Driver::addDynamicLight(const SLight& dl)
s32 CD3D8Driver::addDynamicLight(const SLight& dl)
{
if ((u32)LastSetLight == Caps.MaxActiveLights-1)
return;
CNullDriver::addDynamicLight(dl);
D3DLIGHT8 light;
......@@ -1807,8 +1804,24 @@ void CD3D8Driver::addDynamicLight(const SLight& dl)
light.Phi = dl.OuterCone * 2.0f * core::DEGTORAD;
++LastSetLight;
pID3DDevice->SetLight(LastSetLight, &light);
pID3DDevice->LightEnable(LastSetLight, true);
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);
}
......
......@@ -112,8 +112,15 @@ namespace video
//! deletes all dynamic lights there are
virtual void deleteAllDynamicLights();
//! adds a dynamic light
virtual void addDynamicLight(const SLight& light);
//! 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;
......
......@@ -2078,11 +2078,8 @@ void CD3D9Driver::deleteAllDynamicLights()
//! adds a dynamic light
void CD3D9Driver::addDynamicLight(const SLight& dl)
s32 CD3D9Driver::addDynamicLight(const SLight& dl)
{
if ((u32)LastSetLight == Caps.MaxActiveLights-1)
return;
CNullDriver::addDynamicLight(dl);
D3DLIGHT9 light;
......@@ -2118,8 +2115,26 @@ void CD3D9Driver::addDynamicLight(const SLight& dl)
light.Phi = dl.OuterCone * 2.0f * core::DEGTORAD;
++LastSetLight;
pID3DDevice->SetLight(LastSetLight, &light);
pID3DDevice->LightEnable(LastSetLight, true);
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);
}
......
......@@ -145,8 +145,15 @@ namespace video
//! deletes all dynamic lights there are
virtual void deleteAllDynamicLights();
//! adds a dynamic light
virtual void addDynamicLight(const SLight& light);
//! 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;
......
......@@ -17,7 +17,7 @@ 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)
: ILightSceneNode(parent, mgr, id, position), DriverLightIndex(-1), LightIsOn(true)
{
#ifdef _DEBUG
setDebugName("CLightSceneNode");
......@@ -72,7 +72,9 @@ void CLightSceneNode::render()
break;
}
}
driver->addDynamicLight(LightData);
DriverLightIndex = driver->addDynamicLight(LightData);
setVisible(LightIsOn);
}
......@@ -96,6 +98,19 @@ 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<f32>& CLightSceneNode::getBoundingBox() const
......
......@@ -39,6 +39,12 @@ public:
//! \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<f32>& getBoundingBox() const;
......@@ -89,6 +95,8 @@ private:
video::SLight LightData;
core::aabbox3d<f32> BBox;
s32 DriverLightIndex;
bool LightIsOn;
void doLightRecalc();
};
......
......@@ -818,11 +818,19 @@ void CNullDriver::deleteAllDynamicLights()
//! adds a dynamic light
void CNullDriver::addDynamicLight(const SLight& 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
......
......@@ -216,8 +216,15 @@ namespace video
//! deletes all dynamic lights there are
virtual void deleteAllDynamicLights();
//! adds a dynamic light
virtual void addDynamicLight(const SLight& light);
//! 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;
......
......@@ -352,7 +352,7 @@ 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), LastSetLight(-1),
AntiAlias(params.AntiAlias), RenderTargetTexture(0),
CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), _device(device)
{
#ifdef _DEBUG
......@@ -373,7 +373,7 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
: CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(),
CurrentRenderMode(ERM_NONE), ResetRenderStates(true),
Transformation3DChanged(true), AntiAlias(params.AntiAlias),
RenderTargetTexture(0), LastSetLight(-1), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8)
RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8)
{
#ifdef _DEBUG
setDebugName("COpenGLDriver");
......@@ -410,7 +410,7 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
: CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(),
CurrentRenderMode(ERM_NONE), ResetRenderStates(true),
Transformation3DChanged(true), AntiAlias(params.AntiAlias),
RenderTargetTexture(0), LastSetLight(-1), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8)
RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8)
{
#ifdef _DEBUG
setDebugName("COpenGLDriver");
......@@ -425,6 +425,8 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
//! destructor
COpenGLDriver::~COpenGLDriver()
{
RequestedLights.clear();
deleteMaterialRenders();
// I get a blue screen on my laptop, when I do not delete the
......@@ -2227,28 +2229,50 @@ const wchar_t* COpenGLDriver::getName() const
//! deletes all dynamic lights there are
void COpenGLDriver::deleteAllDynamicLights()
{
for (s32 i=0; i<LastSetLight+1; ++i)
for (s32 i=0; i<MaxLights; ++i)
glDisable(GL_LIGHT0 + i);
LastSetLight = -1;
RequestedLights.clear();
CNullDriver::deleteAllDynamicLights();
}
//! adds a dynamic light
void COpenGLDriver::addDynamicLight(const SLight& light)
s32 COpenGLDriver::addDynamicLight(const SLight& light)
{
if (LastSetLight == MaxLights-1)
return;
CNullDriver::addDynamicLight(light);
RequestedLights.push_back(RequestedLight(light));
u32 newLightIndex = RequestedLights.size() - 1;
// Try and assign a hardware light just now, but don't worry if I can't
assignHardwareLight(newLightIndex);
return (s32)newLightIndex;
}
void COpenGLDriver::assignHardwareLight(u32 lightIndex)
{
setTransform(ETS_WORLD, core::matrix4());
++LastSetLight;
CNullDriver::addDynamicLight(light);
s32 lidx;
for (lidx=GL_LIGHT0; lidx < GL_LIGHT0 + MaxLights; ++lidx)
{
if(!glIsEnabled(lidx))
{
RequestedLights[lightIndex].HardwareLightIndex = lidx;
break;
}
}
if(lidx == GL_LIGHT0 + MaxLights) // There's no room for it just now
return;
s32 lidx = GL_LIGHT0 + LastSetLight;
GLfloat data[4];
const SLight & light = RequestedLights[lightIndex].LightData;
switch (light.Type)
{
......@@ -2325,6 +2349,45 @@ void COpenGLDriver::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
void COpenGLDriver::turnLightOn(s32 lightIndex, bool turnOn)
{
if(lightIndex < 0 || lightIndex >= (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
{
......
......@@ -209,8 +209,15 @@ namespace video
//! deletes all dynamic lights there are
virtual void deleteAllDynamicLights();
//! adds a dynamic light
virtual void addDynamicLight(const SLight& light);
//! 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;
......@@ -367,6 +374,10 @@ namespace video
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);
core::stringw Name;
core::matrix4 Matrices[ETS_COUNT];
......@@ -403,6 +414,19 @@ namespace video
//! Color buffer format
ECOLOR_FORMAT ColorFormat;
//! 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<RequestedLight> RequestedLights;
#ifdef _IRR_WINDOWS_API_
HDC HDc; // Private GDI Device Context
HWND Window;
......
......@@ -14,6 +14,7 @@
#include "IGUIEnvironment.h"
#include "IMaterialRenderer.h"
#include "IReadFile.h"
#include "ILightManager.h"
#include "os.h"
......@@ -162,7 +163,7 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
: 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_COUNT),
MeshCache(cache), CurrentRendertime(ESNRP_COUNT), 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
......@@ -298,6 +299,9 @@ CSceneManager::~CSceneManager()
for (i=0; i<SceneNodeAnimatorFactoryList.size(); ++i)
SceneNodeAnimatorFactoryList[i]->drop();
if(LightManager)
LightManager->drop();
// remove all nodes and animators before dropping the driver
// as render targets may be destroyed twice
removeAll();
......@@ -1163,7 +1167,7 @@ u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDE
// Lighting modell in irrlicht has to be redone..
//if (!isCulled(node))
{
LightList.push_back(DistanceNodeEntry(node, camWorldPos));
LightList.push_back(static_cast<ILightSceneNode*>(node));
taken = 1;
}
break;
......@@ -1284,69 +1288,158 @@ void CSceneManager::drawAll()
// let all nodes register themselves
OnRegisterSceneNode();
if(LightManager)
LightManager->OnPreRender(LightList);
u32 i; // new ISO for scoping problem in some compilers
//render camera scenes
{
CurrentRendertime = ESNRP_CAMERA;
if(LightManager)
LightManager->OnRenderPassPreRender(CurrentRendertime);
for (i=0; i<CameraList.size(); ++i)
CameraList[i]->render();
CameraList.set_used(0);
if(LightManager)
LightManager->OnRenderPassPostRender(CurrentRendertime);
}
//render lights scenes
{
CurrentRendertime = ESNRP_LIGHT;
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<DistanceNodeEntry> 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] = static_cast<ILightSceneNode*>(SortedLights[light].Node);
}
Driver->deleteAllDynamicLights();
Driver->setAmbientLight(AmbientLight);
LightList.sort(); // on distance to camera
u32 maxLights = LightList.size();
if(!LightManager)
maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount(), maxLights);
u32 maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount(), LightList.size() );
for (i=0; i< maxLights; ++i)
LightList[i].Node->render();
LightList[i]->render();
LightList.set_used(0);
if(LightManager)
LightManager->OnRenderPassPostRender(CurrentRendertime);
}
// render skyboxes
{
CurrentRendertime = ESNRP_SKY_BOX;
if(LightManager)
{
LightManager->OnRenderPassPreRender(CurrentRendertime);
for (i=0; i<SkyBoxList.size(); ++i)
{
ISceneNode* node = SkyBoxList[i];
LightManager->OnNodePreRender(node);
node->render();
LightManager->OnNodePostRender(node);
}
}
else
{
for (i=0; i<SkyBoxList.size(); ++i)
SkyBoxList[i]->render();
}
SkyBoxList.set_used(0);
if(LightManager)
LightManager->OnRenderPassPostRender(CurrentRendertime);
}
// render default objects
{
CurrentRendertime = ESNRP_SOLID;
SolidNodeList.sort(); // sort by textures
if(LightManager)
{
LightManager->OnRenderPassPreRender(CurrentRendertime);
for (i=0; i<SolidNodeList.size(); ++i)
{
ISceneNode* node = SolidNodeList[i].Node;
LightManager->OnNodePreRender(node);
node->render();
LightManager->OnNodePostRender(node);
}
}
else
{
for (i=0; i<SolidNodeList.size(); ++i)
SolidNodeList[i].Node->render();
}
Parameters.setAttribute ( "drawn", (s32) SolidNodeList.size() );
SolidNodeList.set_used(0);
if(LightManager)
LightManager->OnRenderPassPostRender(CurrentRendertime);
}
// render shadows
{
CurrentRendertime = ESNRP_SHADOW;
if(LightManager)
{
LightManager->OnRenderPassPreRender(CurrentRendertime);
for (i=0; i<ShadowNodeList.size(); ++i)
{
ISceneNode* node = ShadowNodeList[i];
LightManager->OnNodePreRender(node);
node->render();
LightManager->OnNodePostRender(node);
}
}
else
{
for (i=0; i<ShadowNodeList.size(); ++i)
ShadowNodeList[i]->render();
}
if (!ShadowNodeList.empty())
Driver->drawStencilShadow(true,ShadowColor, ShadowColor,
ShadowColor, ShadowColor);
ShadowNodeList.set_used(0);
if(LightManager)
LightManager->OnRenderPassPostRender(CurrentRendertime);
}
// render transparent objects.
......@@ -1354,17 +1447,50 @@ void CSceneManager::drawAll()
CurrentRendertime = ESNRP_TRANSPARENT;
TransparentNodeList.sort(); // sort by distance from camera
if(LightManager)
{
LightManager->OnRenderPassPreRender(CurrentRendertime);
for (i=0; i<TransparentNodeList.size(); ++i)
{
ISceneNode* node = TransparentNodeList[i].Node;
LightManager->OnNodePreRender(node);
node->render();
LightManager->OnNodePostRender(node);
}
}
else
{
for (i=0; i<TransparentNodeList.size(); ++i)
TransparentNodeList[i].Node->render();
}
TransparentNodeList.set_used(0);
if(LightManager)
LightManager->OnRenderPassPostRender(CurrentRendertime);
}
if(LightManager)
LightManager->OnPostRender();
LightList.set_used(0);
clearDeletionList();
CurrentRendertime = ESNRP_COUNT;
}
void CSceneManager::setLightManager(ILightManager* lightManager)
{
if(LightManager)
LightManager->drop();
LightManager = lightManager;
if(LightManager)
LightManager->grab();
}
//! Sets the color of stencil buffers shadows drawn by the scene manager.
void CSceneManager::setShadowColor(video::SColor color)
......
......@@ -452,6 +452,9 @@ namespace scene
//! 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);
private:
//! Returns a typename from a scene node animator type or null if not found
......@@ -525,8 +528,7 @@ namespace scene
DistanceNodeEntry(ISceneNode* n, const core::vector3df& cameraPos)
: Node(n)
{
Distance = Node->getAbsoluteTransformation().getTranslation().getDistanceFromSQ(cameraPos);
Distance -= Node->getBoundingBox().getExtent().getLengthSQ() * 0.5;
setNodeAndDistanceFromPosition(n, cameraPos);
}
bool operator < (const DistanceNodeEntry& other) const
......@@ -534,6 +536,13 @@ namespace scene
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;
......@@ -556,7 +565,7 @@ namespace scene
//! render pass lists
core::array<ISceneNode*> CameraList;
core::array<DistanceNodeEntry> LightList;
core::array<ILightSceneNode*> LightList;
core::array<ISceneNode*> ShadowNodeList;
core::array<ISceneNode*> SkyBoxList;
core::array<DefaultNodeEntry> SolidNodeList;
......@@ -582,6 +591,10 @@ namespace scene
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;
......
......@@ -1340,13 +1340,11 @@ void CBurningVideoDriver::setAmbientLight(const SColorf& color)
//! adds a dynamic light
void CBurningVideoDriver::addDynamicLight(const SLight& dl)
s32 CBurningVideoDriver::addDynamicLight(const SLight& dl)
{
if ( LightSpace.Light.size () >= getMaximalDynamicLightAmount () )
return;
SBurningShaderLight l;
l.org = dl;
l.LightIsOn = true;
// light in eye space
Transformation[ETS_VIEW].m.transformVect ( &l.posEyeSpace.x, l.org.Position );
......@@ -1371,9 +1369,20 @@ void CBurningVideoDriver::addDynamicLight(const SLight& dl)
}
LightSpace.Light.push_back ( l );
CNullDriver::addDynamicLight( l.org );
(void)CNullDriver::addDynamicLight( l.org );
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()
{
......@@ -1450,6 +1459,9 @@ void CBurningVideoDriver::lightVertex ( s4DVertex *dest, const S3DVertex *source
{
const SBurningShaderLight &light = LightSpace.Light[i];
if(!light.LightIsOn)
continue;
sVec4 vp; // unit vector vertex to light
sVec4 lightHalf; // blinn-phong reflection
......
......@@ -60,8 +60,15 @@ namespace video
//! deletes all dynamic lights there are
virtual void deleteAllDynamicLights();
//! adds a dynamic light
virtual void addDynamicLight(const SLight& light);
//! 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;
......
......@@ -27,6 +27,7 @@ namespace video
struct SBurningShaderLight
{
SLight org;
bool LightIsOn;
sVec4 posEyeSpace;
......
......@@ -862,6 +862,10 @@
RelativePath=".\..\..\include\IDummyTransformationSceneNode.h"
>
</File>
<File
RelativePath="..\..\include\ILightManager.h"
>
</File>
<File
RelativePath=".\..\..\include\ILightSceneNode.h"
>
......
Test suite pass at GMT Tue Jan 06 15:57:25 2009
Test suite pass at GMT Mon Jan 12 10:46:46 2009
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment