Merge branch 'ryzom/ark-features' into main/gingo-test
[ryzomcore.git] / nel / src / 3d / point_light_model.cpp
blob17bb18619adbbc575a28959c5f623ee243fcc6a5
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
19 #include "nel/3d/point_light_model.h"
20 #include "nel/3d/light_trav.h"
21 #include "nel/3d/root_model.h"
22 #include "nel/3d/skeleton_model.h"
23 #include "nel/3d/scene.h"
26 using namespace NLMISC;
28 #ifdef DEBUG_NEW
29 #define new DEBUG_NEW
30 #endif
32 namespace NL3D {
35 // ***************************************************************************
36 void CPointLightModel::registerBasic()
38 CScene::registerModel( PointLightModelId, TransformId, CPointLightModel::creator);
41 // ***************************************************************************
42 CPointLightModel::CPointLightModel()
44 _DeltaPosToSkeletonWhenOutOfFrustum.set(0, 0, 1.5f);
45 _TimeFromLastClippedSpotDirection= 0;
46 _InfluenceLightMap= false;
50 // ***************************************************************************
51 CPointLightModel::~CPointLightModel()
56 // ***************************************************************************
57 void CPointLightModel::initModel()
59 CTransform::initModel();
61 // link me to the root of light.
62 getOwnerScene()->getLightTrav().addPointLightModel(this);
67 // ***************************************************************************
68 void CPointLightModel::setDeltaPosToSkeletonWhenOutOfFrustum(const CVector &deltaPos)
70 _DeltaPosToSkeletonWhenOutOfFrustum= deltaPos;
74 // ***************************************************************************
75 const CVector &CPointLightModel::getDeltaPosToSkeletonWhenOutOfFrustum() const
77 return _DeltaPosToSkeletonWhenOutOfFrustum;
81 // ***************************************************************************
82 void CPointLightModel::traverseLight()
84 CLightTrav &lightTrav= getOwnerScene()->getLightTrav();
86 // Note: any dynamic light is supposed to always move each frame, so they are re-inserted in the
87 // quadGrid each frame.
90 // reset all models lighted by this light.
91 // Then models are marked dirty and their light setup is reseted
92 PointLight.resetLightedModels();
95 // if the light is visible (ie not hiden)
96 if( isHrcVisible() )
98 // If the light is not hidden by any skeleton.
99 if( isClipVisible() )
101 // recompute the worldPosition of the light.
102 PointLight.setPosition( getWorldMatrix().getPos() );
104 // recompute the worldSpotDirection of the light.
105 if(PointLight.getType() == CPointLight::SpotLight)
107 // Interpolate over time. (hardcoded)
108 _TimeFromLastClippedSpotDirection-= 0.05f;
109 if(_TimeFromLastClippedSpotDirection <= 0)
111 PointLight.setupSpotDirection(getWorldMatrix().getJ());
113 else
115 CVector actualSpotDir= getWorldMatrix().getJ();
116 // Interpolate
117 float t= _TimeFromLastClippedSpotDirection;
118 CVector interpSpotDir= actualSpotDir*(1-t) + _LastWorldSpotDirectionWhenOutOfFrustum * t;
119 // set the interpolated one.
120 PointLight.setupSpotDirection(interpSpotDir);
124 else
126 // We are hidden because a skeleton has hide us, or created during anim detail traversal (or else don't know why).
127 // NB: a point light can't be in a cluster since it is not a transformShape...
128 if (!_AncestorSkeletonModel) return;
129 const CMatrix &skMatrix= _AncestorSkeletonModel->getWorldMatrix();
131 PointLight.setPosition( skMatrix * _DeltaPosToSkeletonWhenOutOfFrustum );
133 // recompute the worldSpotDirection of the light.
134 if(PointLight.getType() == CPointLight::SpotLight)
136 // If last frame, this pointLight was visible (Time is not 1)
137 if(_TimeFromLastClippedSpotDirection != 1)
139 // Take the current World spot direction
140 _LastWorldSpotDirectionWhenOutOfFrustum= PointLight.getSpotDirection();
141 // reset time.
142 _TimeFromLastClippedSpotDirection= 1;
145 // Don't need to modify PointLight spot direction since already setuped (when model was visible)
149 // now, insert this light in the quadGrid. NB: in CLightTrav::traverse(), the quadGrid is cleared before here.
150 // This light will touch (resetLighting()) any model it may influence.
151 lightTrav.LightingManager.addDynamicLight(&PointLight);
154 // if this light is the one that should influence the lightmapped objects
155 if(_InfluenceLightMap)
157 // setup a light with attenuation, for more accurate vertex lighting
158 CLight vertexLight;
160 // setup position/type/direction/color
161 if(PointLight.getType()!=CPointLight::SpotLight)
162 vertexLight.setupPointLight(CRGBA::Black, PointLight.getDiffuse(), PointLight.getSpecular(),
163 PointLight.getPosition(), CVector::K);
164 else
165 vertexLight.setupSpotLight(CRGBA::Black, PointLight.getDiffuse(), PointLight.getSpecular(),
166 PointLight.getPosition(), PointLight.getSpotDirection(), 1, float(Pi)/2);
168 // setup attenuation
169 vertexLight.setupAttenuation(PointLight.getAttenuationBegin(), PointLight.getAttenuationEnd());
171 // setup hotspot for spotLight
172 if(PointLight.getType()==CPointLight::SpotLight)
174 // hotspot == where attenuation should be 0.9
175 vertexLight.setupSpotExponent(PointLight.getSpotAngleBegin()*0.9f + PointLight.getSpotAngleEnd()*0.1f);
178 // setup the driver
179 getOwnerScene()->getDriver()->setLightMapDynamicLight(true, vertexLight);
187 } // NL3D