Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / src / 3d / frustum.cpp
blob36d28ebb018322f41b1bf5b6ceb61b83feefa65e
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/frustum.h"
20 #include "nel/misc/matrix.h"
21 #include <cmath>
24 using namespace NLMISC;
26 #ifdef DEBUG_NEW
27 #define new DEBUG_NEW
28 #endif
30 namespace NL3D
34 void CFrustum::init(float left, float right, float bottom, float top, float znear, float zfar, bool perspective)
36 Left= left;
37 Right= right;
38 Bottom= bottom;
39 Top= top;
40 Near= znear;
41 Far= zfar;
42 Perspective= perspective;
45 void CFrustum::init(float width, float height, float znear, float zfar, bool perspective)
47 init(-width/2, width/2, -height/2, height/2, znear, zfar, perspective);
49 void CFrustum::initPerspective(float fov, float aspectRatio, float znear, float zfar)
51 float w,h;
52 w= 2*znear*(float)tan(fov/2);
53 h= aspectRatio != 0.f ? w/aspectRatio : 0.f;
54 init(w,h,znear,zfar,true);
56 void CFrustum::getValues(float &left, float &right, float &bottom, float &top, float &znear, float &zfar) const
58 left= Left;
59 right= Right;
60 bottom= Bottom;
61 top= Top;
62 znear= Near;
63 zfar= Far;
67 // ***************************************************************************
68 CVector CFrustum::project(const CVector &vec) const
70 CVector ret;
71 float decalX, decalY;
72 float w, h;
73 float OOw, OOh;
75 // Fast transform to openGL like axis.
76 CVector pt;
77 pt.x= vec.x;
78 pt.y= vec.z;
79 pt.z= -vec.y;
81 decalX= (Right+Left);
82 decalY= (Top+Bottom);
83 w= Right-Left;
84 h= Top-Bottom;
85 OOw= 1.0f/w;
86 OOh= 1.0f/h;
88 // project to -1..+1.
89 if(Perspective)
91 ret.x= (2*Near*pt.x + decalX*pt.z)*OOw;
92 ret.x/= -pt.z;
93 ret.y= (2*Near*pt.y + decalY*pt.z)*OOh;
94 ret.y/= -pt.z;
96 else
98 ret.x= (2*pt.x-decalX)*OOw;
99 ret.y= (2*pt.y-decalY)*OOh;
103 // Map it to 0..1.
104 ret.x= 0.5f*(ret.x+1);
105 ret.y= 0.5f*(ret.y+1);
106 ret.z= 0;
108 return ret;
112 // ***************************************************************************
113 CVector CFrustum::projectZ(const CVector &vec) const
115 CVector ret;
116 float decalX, decalY;
117 float w, h;
118 float OOw = 1.0f, OOh = 1.0f;
120 // Fast transform to openGL like axis.
121 CVector pt;
122 pt.x= vec.x;
123 pt.y= vec.z;
124 pt.z= -vec.y;
126 decalX= (Right+Left);
127 decalY= (Top+Bottom);
128 w= Right-Left;
129 h= Top-Bottom;
130 if (w) OOw /= w;
131 if (h) OOh /= h;
133 // project to -1..+1.
134 if(Perspective)
136 ret.x= (2*Near*pt.x + decalX*pt.z)*OOw;
137 ret.x/= -pt.z;
138 ret.y= (2*Near*pt.y + decalY*pt.z)*OOh;
139 ret.y/= -pt.z;
141 else
143 ret.x= (2*pt.x-decalX)*OOw;
144 ret.y= (2*pt.y-decalY)*OOh;
148 // Map it to 0..1.
149 ret.x= 0.5f*(ret.x+1);
150 ret.y= 0.5f*(ret.y+1);
151 ret.z= pt.z;
153 return ret;
157 // ***************************************************************************
158 CVector CFrustum::unProject(const CVector &vec) const
160 CVector ret;
161 float decalX, decalY;
162 float w, h;
164 decalX= (Right+Left);
165 decalY= (Top+Bottom);
166 w= Right-Left;
167 h= Top-Bottom;
169 // vec is a vector in a left hand axis.
170 CVector pt;
171 pt.x= vec.x;
172 pt.y= vec.y;
173 pt.z= vec.z;
175 // Map it to -1..1
176 pt.x= 2*(pt.x-0.5f);
177 pt.y= 2*(pt.y-0.5f);
179 // Map Z to Near..Far.
180 // Z IN is 1/Z, and is in 0..1.
181 // inverse to 1..0.
182 pt.z= 1-pt.z;
183 // Map ret.z to 1/Far..1/Near.
184 pt.z= 1/Far+(1/Near-1/Far)*pt.z;
185 // Inverse, so ret.z E Near..Far.
186 pt.z= 1/pt.z;
187 // Actually, pt.z==w, homogenous coordinate.
190 // unproject
191 if(Perspective)
193 // w of homogenous coordinate.
194 float Wh;
195 float Zin;
196 Wh= pt.z;
197 Zin= -pt.z;
199 // unproject. (Projection is: x'= x/w. y'= y/w).
200 pt.x= pt.x*Wh;
201 pt.y= pt.y*Wh;
202 ret.x= (pt.x*w-decalX*Zin)/(2*Near);
203 ret.y= (pt.y*h-decalY*Zin)/(2*Near);
204 ret.z= Zin;
206 else
208 // NOT DONE YET.
209 nlstop;
210 /*ret.x= (pt.x*w+decalX)/2;
211 ret.y= (pt.y*h+decalY)/2;
215 // Fast transform from openGL like axis.
216 pt =ret;
217 ret.x= pt.x;
218 ret.y= -pt.z;
219 ret.z= pt.y;
221 return ret;
225 // ***************************************************************************
226 CVector CFrustum::unProjectZ(const CVector &vec) const
228 CVector ret;
229 float decalX, decalY;
230 float w, h;
232 decalX= (Right+Left);
233 decalY= (Top+Bottom);
234 w= Right-Left;
235 h= Top-Bottom;
237 // vec is a vector in a left hand axis.
238 CVector pt;
239 pt.x= vec.x;
240 pt.y= vec.y;
241 pt.z= vec.z;
243 // Map it to -1..1
244 pt.x= 2*(pt.x-0.5f);
245 pt.y= 2*(pt.y-0.5f);
247 // unproject
248 if(Perspective)
250 // w of homogenous coordinate.
251 float Wh;
252 float Zin;
253 Wh= pt.z;
254 Zin= -pt.z;
256 // unproject. (Projection is: x'= x/w. y'= y/w).
257 pt.x= pt.x*Wh;
258 pt.y= pt.y*Wh;
259 ret.x= (pt.x*w-decalX*Zin)/(2*Near);
260 ret.y= (pt.y*h-decalY*Zin)/(2*Near);
261 ret.z= Zin;
263 else
265 // NOT DONE YET.
266 //nlstop;
267 /*ret.x= (pt.x*w+decalX)/2;
268 ret.y= (pt.y*h+decalY)/2;
270 // Yoyo: crash avoid for lem
271 ret= vec;
274 // Fast transform from openGL like axis.
275 pt =ret;
276 ret.x= pt.x;
277 ret.y= -pt.z;
278 ret.z= pt.y;
280 return ret;
283 // ***************************************************************************
284 float CFrustum::getAspectRatio() const
286 float w= Right-Left;
287 float h= Top-Bottom;
288 if(h!=0)
289 return w/h;
290 else
291 return 1.f;
295 } // NL3D