Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / driver / direct3d / driver_direct3d_matrix.cpp
blob988f9c9ebd0a5fbd3f594688c37b39e9c96c8eee
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 "stddirect3d.h"
19 #include "nel/3d/vertex_buffer.h"
20 #include "nel/3d/light.h"
21 #include "nel/3d/index_buffer.h"
22 #include "nel/misc/rect.h"
23 #include "nel/3d/viewport.h"
24 #include "nel/3d/scissor.h"
25 #include "nel/3d/u_driver.h"
27 #include "driver_direct3d.h"
29 #ifdef DEBUG_NEW
30 #define new DEBUG_NEW
31 #endif
33 using namespace std;
34 using namespace NLMISC;
36 namespace NL3D
39 // ***************************************************************************
41 void CDriverD3D::updateMatrices ()
43 H_AUTO_D3D(CDriver3D_updateMatrices );
44 // Update view model matrix
45 D3DXMatrixMultiply (&_D3DModelView, &(_MatrixCache[remapMatrixIndex (D3DTS_WORLD)].Matrix), &(_MatrixCache[remapMatrixIndex (D3DTS_VIEW)].Matrix));
47 // Update view model projection matrix
48 _D3DModelViewProjection = _D3DModelView;
49 D3DXMatrixMultiply (&_D3DModelViewProjection, &_D3DModelViewProjection, &(_MatrixCache[remapMatrixIndex (D3DTS_PROJECTION)].Matrix));
51 // Update the inverted view model matrix
52 D3DXMatrixInverse (&_D3DInvModelView, NULL, &_D3DModelView);
54 // Update the normalize state
55 setRenderState (D3DRS_NORMALIZENORMALS, (_UserViewMtx.hasScalePart() || _UserModelMtx.hasScalePart() || _ForceNormalize)?TRUE:FALSE);
58 // ***************************************************************************
60 void CDriverD3D::updateProjectionMatrix ()
62 H_AUTO_D3D(CDriver3D_updateProjectionMatrix );
63 float left = _FrustumLeft;
64 float right = _FrustumRight;
65 float top = _FrustumTop;
66 float bottom = _FrustumBottom;
68 if (_RenderTarget.Texture)
69 swap (bottom, top);
71 // Get the render target size
72 uint32 clientWidth;
73 uint32 clientHeight;
74 getRenderTargetSize (clientWidth, clientHeight);
76 // In D3D, the center of the first screen pixel is [0.0,0.0]. Is NeL it is [0.5,0.5]
77 const float addW = (right-left)/(2*(_Viewport.getWidth() * (float)clientWidth));
78 const float addH = (bottom-top)/(2*(_Viewport.getHeight() * (float)clientHeight));
80 left += addW;
81 right += addW;
82 top += addH;
83 bottom += addH;
85 D3DXMATRIX projection;
86 if (_FrustumPerspective)
88 D3DXMatrixPerspectiveOffCenterLH (&projection, left, right, bottom, top, _FrustumZNear, _FrustumZFar);
90 else
92 D3DXMatrixOrthoOffCenterLH (&projection, left, right, bottom, top, _FrustumZNear, _FrustumZFar);
94 setMatrix (D3DTS_PROJECTION, projection);
96 // Backup znear and zfar for zbias setup
97 _OODeltaZ = 1 / (_FrustumZFar - _FrustumZNear);
99 updateMatrices ();
102 // ***************************************************************************
104 void CDriverD3D::setFrustum(float left, float right, float bottom, float top, float znear, float zfar, bool perspective)
106 H_AUTO_D3D(CDriverD3D_setFrustum)
107 _FrustumLeft = left;
108 _FrustumRight = right;
109 _FrustumTop = top;
110 _FrustumBottom = bottom;
111 _FrustumZNear = znear;
112 _FrustumZFar = zfar;
113 _FrustumPerspective = perspective;
114 updateProjectionMatrix ();
118 // ***************************************************************************
120 void CDriverD3D::setFrustumMatrix(CMatrix &frustumMatrix)
122 H_AUTO_D3D(CDriverD3D_setFrustum)
124 frustumMatrix.transpose();
125 setMatrix (D3DTS_PROJECTION, D3DXMATRIX(frustumMatrix.get()));
128 // ***************************************************************************
130 CMatrix CDriverD3D::getFrustumMatrix()
132 H_AUTO_D3D(CDriverD3D_getFrustum)
134 CMatrix frustumMatrix;
135 frustumMatrix.set((float *)_MatrixCache[D3DTS_PROJECTION].Matrix.m);
136 frustumMatrix.transpose();
138 return frustumMatrix;
141 // ***************************************************************************
143 void CDriverD3D::setupViewMatrix(const CMatrix& mtx)
145 H_AUTO_D3D(CDriverD3D_setupViewMatrix)
146 // Remember the view matrix
147 _UserViewMtx= mtx;
148 _PZBCameraPos= CVector::Null;
150 // Set the driver matrix
151 D3DXMATRIX view;
152 NL_D3D_MATRIX (view, mtx);
154 // Pass to directx matrix basis
155 swap (view._12, view._13);
156 swap (view._22, view._23);
157 swap (view._32, view._33);
158 swap (view._42, view._43);
160 setMatrix (D3DTS_VIEW, view);
162 // Set the spacular matrix
163 CMatrix specularTex;
164 specularTex = mtx;
165 specularTex.setPos(CVector(0.0f,0.0f,0.0f));
166 specularTex.invert();
167 NL_D3D_MATRIX (_D3DSpecularWorldTex, specularTex);
169 updateMatrices ();
172 // ***************************************************************************
174 void CDriverD3D::setupViewMatrixEx(const CMatrix& mtx, const CVector &cameraPos)
176 H_AUTO_D3D(CDriverD3D_setupViewMatrixEx)
177 // Remeber the view matrix
178 _UserViewMtx= mtx;
179 _PZBCameraPos= cameraPos;
181 // Set the driver matrix
182 D3DXMATRIX view;
183 NL_D3D_MATRIX (view, mtx);
185 // Pass to directx matrix basis
186 swap (view._12, view._13);
187 swap (view._22, view._23);
188 swap (view._32, view._33);
189 swap (view._42, view._43);
191 // Reset the viewMtx position.
192 view._41 = 0;
193 view._42 = 0;
194 view._43 = 0;
196 setMatrix (D3DTS_VIEW, view);
198 // Set the spacular matrix
199 CMatrix specularTex;
200 specularTex = mtx;
201 NL_D3D_MATRIX (_D3DSpecularWorldTex, specularTex);
202 swap (_D3DSpecularWorldTex._12, _D3DSpecularWorldTex._13);
203 swap (_D3DSpecularWorldTex._22, _D3DSpecularWorldTex._23);
204 swap (_D3DSpecularWorldTex._32, _D3DSpecularWorldTex._33);
205 swap (_D3DSpecularWorldTex._42, _D3DSpecularWorldTex._43);
206 _D3DSpecularWorldTex._41 = 0;
207 _D3DSpecularWorldTex._42 = 0;
208 _D3DSpecularWorldTex._43 = 0;
210 D3DXMatrixInverse ( &_D3DSpecularWorldTex, NULL, &_D3DSpecularWorldTex);
211 swap (_D3DSpecularWorldTex._12, _D3DSpecularWorldTex._13);
212 swap (_D3DSpecularWorldTex._22, _D3DSpecularWorldTex._23);
213 swap (_D3DSpecularWorldTex._32, _D3DSpecularWorldTex._33);
214 swap (_D3DSpecularWorldTex._42, _D3DSpecularWorldTex._43);
216 updateMatrices ();
219 // ***************************************************************************
221 void CDriverD3D::setupModelMatrix(const CMatrix& mtx)
223 H_AUTO_D3D(CDriverD3D_setupModelMatrix)
224 // Stats
225 _NbSetupModelMatrixCall++;
227 // Remeber the model matrix
228 _UserModelMtx= mtx;
230 D3DXMATRIX world;
231 NL_D3D_MATRIX (world, mtx);
233 // Remove from position the camera position
234 world._41 -= _PZBCameraPos.x;
235 world._42 -= _PZBCameraPos.y;
236 world._43 -= _PZBCameraPos.z;
238 setMatrix (D3DTS_WORLD, world);
240 updateMatrices ();
243 // ***************************************************************************
245 CMatrix CDriverD3D::getViewMatrix() const
247 H_AUTO_D3D(CDriverD3D_getViewMatrix)
248 return _UserViewMtx;
251 // ***************************************************************************
253 void CDriverD3D::forceNormalize(bool normalize)
255 H_AUTO_D3D(CDriverD3D_forceNormalize)
256 _ForceNormalize = normalize;
257 updateMatrices ();
260 // ***************************************************************************
262 bool CDriverD3D::isForceNormalize() const
264 H_AUTO_D3D(CDriverD3D_isForceNormalize)
265 return _RenderStateCache[D3DRS_NORMALIZENORMALS].Value != FALSE;
270 // ***************************************************************************
272 void CDriverD3D::setupScissor (const class CScissor& scissor)
274 H_AUTO_D3D(CDriverD3D_setupScissor )
275 if (!_ScissorTouched &&
276 _Scissor.X == scissor.X &&
277 _Scissor.Y == scissor.Y &&
278 _Scissor.Width == scissor.Width &&
279 _Scissor.Height == scissor.Height
280 ) return;
281 nlassert (_DeviceInterface);
283 // Get viewport
284 _ScissorTouched = false;
285 float x= scissor.X;
286 float y= scissor.Y;
287 float width= scissor.Width;
288 float height= scissor.Height;
290 if(x==0 && y==0 && width==1 && height==1)
292 setRenderState (D3DRS_SCISSORTESTENABLE, FALSE);
294 else
296 if (_HWnd)
298 // Get the render target size
299 uint32 clientWidth;
300 uint32 clientHeight;
301 getRenderTargetSize (clientWidth, clientHeight);
303 // Setup d3d scissor
305 RECT rect;
306 rect.left=(int)floor((float)clientWidth * x + 0.5f);
307 clamp (rect.left, 0, (int)clientWidth);
308 if (_RenderTarget.Texture)
309 rect.top=(int)floor((float)clientHeight* y + 0.5f);
310 else
311 rect.top=(int)floor((float)clientHeight* (1-y-height) + 0.5f);
312 clamp (rect.top, 0, (int)clientHeight);
314 rect.right=(int)floor((float)clientWidth * (x+width) + 0.5f );
315 clamp (rect.right, 0, (int)clientWidth);
316 if (_RenderTarget.Texture)
317 rect.bottom=(int)floor((float)clientHeight* (y+height) + 0.5f);
318 else
319 rect.bottom=(int)floor((float)clientHeight* (1-y) + 0.5f);
320 clamp (rect.bottom, 0, (int)clientHeight);
323 H_AUTO_D3D(CDriverD3D_setupScissorDevice )
324 _DeviceInterface->SetScissorRect (&rect);
326 setRenderState (D3DRS_SCISSORTESTENABLE, TRUE);
331 // Backup the scissor
332 _Scissor = scissor;
335 // ***************************************************************************
337 void CDriverD3D::setupViewport (const class CViewport& viewport)
339 H_AUTO_D3D(CDriverD3D_setupViewport )
340 if (_HWnd == NULL)
341 return;
343 // Get the render target size
344 uint32 clientWidth;
345 uint32 clientHeight;
346 getRenderTargetSize (clientWidth, clientHeight);
348 // Get viewport
349 float x;
350 float y;
351 float width;
352 float height;
353 viewport.getValues (x, y, width, height);
355 // Get integer values
356 int ix=(int)((float)clientWidth*x);
357 clamp (ix, 0, (int)clientWidth);
358 int iy;
359 if (_RenderTarget.Texture)
360 iy=(int)((float)clientHeight*y);
361 else
362 iy=(int)((float)clientHeight*(1.f-(y+height)));
363 clamp (iy, 0, (int)clientHeight);
364 int iwidth=(int)((float)clientWidth*width);
365 clamp (iwidth, 0, (int)clientWidth-ix);
366 int iheight=(int)((float)clientHeight*height);
367 clamp (iheight, 0, (int)clientHeight-iy);
369 // Setup D3D viewport
370 _D3DViewport.X = ix;
371 _D3DViewport.Y = iy;
372 _D3DViewport.Width = iwidth;
373 _D3DViewport.Height = iheight;
374 _D3DViewport.MinZ = _DepthRangeNear;
375 _D3DViewport.MaxZ = _DepthRangeFar;
376 _DeviceInterface->SetViewport (&_D3DViewport);
378 // Backup the viewport
379 _Viewport = viewport;
381 updateProjectionMatrix ();
384 // ***************************************************************************
385 void CDriverD3D::setDepthRange(float znear, float zfar)
387 H_AUTO_D3D(CDriverD3D_setDepthRange)
388 nlassert(znear != zfar);
389 if (_HWnd == NULL)
390 return;
391 #ifdef NL_D3D_USE_RENDER_STATE_CACHE
392 NL_D3D_CACHE_TEST(CacheTest_DepthRange, znear != _DepthRangeNear || zfar != _DepthRangeFar)
393 #endif
395 _DepthRangeNear = znear;
396 _DepthRangeFar = zfar;
397 _D3DViewport.MinZ = _DepthRangeNear;
398 _D3DViewport.MaxZ = _DepthRangeFar;
399 _DeviceInterface->SetViewport (&_D3DViewport);
403 // ***************************************************************************
404 void CDriverD3D::getDepthRange(float &znear, float &zfar) const
406 H_AUTO_D3D(CDriverD3D_getDepthRange)
407 znear = _DepthRangeNear;
408 zfar = _DepthRangeFar;
411 // ***************************************************************************
413 void CDriverD3D::getViewport(CViewport &viewport)
415 H_AUTO_D3D(CDriverD3D_getViewport)
416 viewport = _Viewport;
419 // ***************************************************************************
422 } // NL3D