1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
19 #include "nel/3d/camera.h"
20 #include "nel/3d/scene.h"
30 // ***************************************************************************
31 void CCamera::registerBasic()
33 CScene::registerModel(CameraId
, TransformId
, CCamera::creator
);
37 // ***************************************************************************
40 setFrustum(1.0f
, 1.0f
, 0.01f
, 1.0f
);
43 IAnimatable::resize(AnimValueLast
);
45 _FovAnimationEnabled
= false;
46 _TargetAnimationEnabled
= false;
47 _FovAnimationAspectRatio
= 4.0f
/3.0f
;
50 _Fov
.Value
= (float)NLMISC::Pi
/2;
51 _Target
.Value
= CVector::Null
;
54 // ***************************************************************************
55 void CCamera::setFrustum(float left
, float right
, float bottom
, float top
, float znear
, float zfar
, bool perspective
)
57 _Frustum
.init( left
, right
,bottom
, top
, znear
, zfar
, perspective
);
59 // ***************************************************************************
60 void CCamera::setFrustum(float width
, float height
, float znear
, float zfar
, bool perspective
)
62 _Frustum
.init(width
, height
, znear
, zfar
, perspective
);
64 // ***************************************************************************
65 void CCamera::setPerspective(float fov
, float aspectRatio
, float znear
, float zfar
)
67 _Frustum
.initPerspective(fov
, aspectRatio
, znear
, zfar
);
69 // ***************************************************************************
70 void CCamera::getFrustum(float &left
, float &right
, float &bottom
, float &top
, float &znear
, float &zfar
) const
73 right
= _Frustum
.Right
;
74 bottom
= _Frustum
.Bottom
;
79 // ***************************************************************************
80 bool CCamera::isOrtho() const
82 return !_Frustum
.Perspective
;
84 // ***************************************************************************
85 bool CCamera::isPerspective() const
87 return _Frustum
.Perspective
;
91 // ***************************************************************************
92 // ***************************************************************************
94 // ***************************************************************************
95 // ***************************************************************************
99 // ***************************************************************************
100 IAnimatedValue
* CCamera::getValue (uint valueId
)
105 case FovValue
: return &_Fov
;
106 case TargetValue
: return &_Target
;
107 case RollValue
: return &_Roll
;
110 return CTransform::getValue(valueId
);
112 // ***************************************************************************
113 const char *CCamera::getValueName (uint valueId
) const
118 case FovValue
: return getFovValueName();
119 case TargetValue
: return getTargetValueName();
120 case RollValue
: return getRollValueName();
123 return CTransform::getValueName(valueId
);
126 // ***************************************************************************
127 CTrackDefaultFloat
CCamera::DefaultFov( (float)NLMISC::Pi
/2 );
128 CTrackDefaultFloat
CCamera::DefaultRoll( 0 );
131 ITrack
* CCamera::getDefaultTrack (uint valueId
)
136 case PosValue
: return &_DefaultPos
;
137 case FovValue
: return &DefaultFov
;
138 case TargetValue
: return &_DefaultTargetPos
;
139 case RollValue
: return &DefaultRoll
;
142 return CTransform::getDefaultTrack(valueId
);
144 // ***************************************************************************
145 void CCamera::registerToChannelMixer(CChannelMixer
*chanMixer
, const std::string
&prefix
)
147 // For CCamera, channels are not detailled.
148 addValue(chanMixer
, FovValue
, OwnerBit
, prefix
, false);
149 addValue(chanMixer
, TargetValue
, OwnerBit
, prefix
, false);
150 addValue(chanMixer
, RollValue
, OwnerBit
, prefix
, false);
152 CTransform::registerToChannelMixer(chanMixer
, prefix
);
157 // ***************************************************************************
158 void CCamera::update()
161 if(IAnimatable::isTouched(OwnerBit
) || IAnimatable::isTouched(ITransformable::OwnerBit
))
164 if( _FovAnimationEnabled
&& IAnimatable::isTouched(FovValue
))
166 // keep the same near/far.
167 setPerspective(_Fov
.Value
, _FovAnimationAspectRatio
, _Frustum
.Near
, _Frustum
.Far
);
168 IAnimatable::clearFlag(FovValue
);
172 // If target/Roll is animated, compute our own quaternion.
173 if( _TargetAnimationEnabled
&& (IAnimatable::isTouched(TargetValue
) || IAnimatable::isTouched(RollValue
) || IAnimatable::isTouched(PosValue
)) )
175 lookAt (getPos (), _Target
.Value
, -_Roll
.Value
);
177 IAnimatable::clearFlag(TargetValue
);
178 IAnimatable::clearFlag(RollValue
);
182 CTransform::update();
185 IAnimatable::clearFlag(OwnerBit
);
189 // ***************************************************************************
190 void CCamera::build (const CCameraInfo
&cameraInfo
)
193 enableTargetAnimation(cameraInfo
.TargetMode
);
194 enableFovAnimation(cameraInfo
.UseFov
);
195 if (cameraInfo
.TargetMode
)
198 setTransformMode (ITransformable::RotQuat
);
199 setTargetPos (cameraInfo
.TargetPos
);
200 _DefaultTargetPos
.setDefaultValue (cameraInfo
.TargetPos
);
201 setRoll (cameraInfo
.Roll
);
203 if (cameraInfo
.UseFov
)
205 setFov (cameraInfo
.Fov
);
207 setPos (cameraInfo
.Pos
);
208 _DefaultPos
.setDefaultValue (cameraInfo
.Pos
);
212 // ***************************************************************************
213 CCameraInfo::CCameraInfo ()
222 // ***************************************************************************
223 void CCameraInfo::serial (NLMISC::IStream
&s
)
228 s
.serial (TargetPos
);
231 s
.serial (TargetMode
);
236 // ***************************************************************************
237 void CCamera::buildCameraPyramid(std::vector
<CPlane
> &pyramid
, bool useWorldMatrix
)
241 // Compute pyramid in view basis.
243 CVector
lb(_Frustum
.Left
, _Frustum
.Near
, _Frustum
.Bottom
);
244 CVector
lt(_Frustum
.Left
, _Frustum
.Near
, _Frustum
.Top
);
245 CVector
rb(_Frustum
.Right
, _Frustum
.Near
, _Frustum
.Bottom
);
246 CVector
rt(_Frustum
.Right
, _Frustum
.Near
, _Frustum
.Top
);
248 CVector
lbFar(_Frustum
.Left
, _Frustum
.Far
, _Frustum
.Bottom
);
249 CVector
ltFar(_Frustum
.Left
, _Frustum
.Far
, _Frustum
.Top
);
250 CVector
rbFar(_Frustum
.Right
, _Frustum
.Far
, _Frustum
.Bottom
);
251 CVector
rtFar(_Frustum
.Right
, _Frustum
.Far
, _Frustum
.Top
);
254 pyramid
[0].make(lt
, lb
, rt
);
256 pyramid
[1].make(lbFar
, ltFar
, rtFar
);
258 if(_Frustum
.Perspective
)
261 pyramid
[2].make(pfoc
, lt
, lb
);
263 pyramid
[3].make(pfoc
, rt
, lt
);
265 pyramid
[4].make(pfoc
, rb
, rt
);
267 pyramid
[5].make(pfoc
, lb
, rb
);
272 pyramid
[2].make(lt
, ltFar
, lbFar
);
274 pyramid
[3].make(lt
, rtFar
, ltFar
);
276 pyramid
[4].make(rt
, rbFar
, rtFar
);
278 pyramid
[5].make(lb
, lbFar
, rbFar
);
282 CMatrix invCamMatrix
;
284 invCamMatrix
= getWorldMatrix();
286 invCamMatrix
= getMatrix();
287 invCamMatrix
.invert();
289 // Compute pyramid in World basis.
290 // The vector transformation M of a plane p is computed as p*M-1.
291 for (uint i
= 0; i
< 6; i
++)
293 pyramid
[i
]= pyramid
[i
]*invCamMatrix
;
297 // ***************************************************************************
298 void CCamera::buildCameraPyramidCorners(std::vector
<NLMISC::CVector
> &pyramidCorners
, bool useWorldMatrix
)
300 pyramidCorners
.resize(8);
301 pyramidCorners
[0].set(_Frustum
.Left
, _Frustum
.Near
, _Frustum
.Bottom
);
302 pyramidCorners
[1].set(_Frustum
.Left
, _Frustum
.Near
, _Frustum
.Top
);
303 pyramidCorners
[2].set(_Frustum
.Right
, _Frustum
.Near
, _Frustum
.Bottom
);
304 pyramidCorners
[3].set(_Frustum
.Right
, _Frustum
.Near
, _Frustum
.Top
);
305 float f
= _Frustum
.Perspective
? (_Frustum
.Far
/ _Frustum
.Near
) : 1.f
;
306 pyramidCorners
[4].set(f
* _Frustum
.Left
, _Frustum
.Far
, f
* _Frustum
.Bottom
);
307 pyramidCorners
[5].set(f
* _Frustum
.Left
, _Frustum
.Far
, f
* _Frustum
.Top
);
308 pyramidCorners
[6].set(f
* _Frustum
.Right
, _Frustum
.Far
, f
* _Frustum
.Bottom
);
309 pyramidCorners
[7].set(f
* _Frustum
.Right
, _Frustum
.Far
, f
* _Frustum
.Top
);
311 const CMatrix
&camMatrix
= useWorldMatrix
? getWorldMatrix() : getMatrix();
312 for(uint k
= 0; k
< 8; ++k
)
314 pyramidCorners
[k
] = camMatrix
* pyramidCorners
[k
];