xref: /trunk/main/svx/source/engine3d/camera3d.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 #include <svx/camera3d.hxx>
31 #include <tools/stream.hxx>
32 
33 /*************************************************************************
34 |*
35 |* Konstruktor
36 |*
37 \************************************************************************/
38 
39 Camera3D::Camera3D(const basegfx::B3DPoint& rPos, const basegfx::B3DPoint& rLookAt,
40                    double fFocalLen, double fBankAng) :
41     aResetPos(rPos),
42     aResetLookAt(rLookAt),
43     fResetFocalLength(fFocalLen),
44     fResetBankAngle(fBankAng),
45     fBankAngle(fBankAng),
46     bAutoAdjustProjection(sal_True)
47 {
48     SetVPD(0);
49     SetPosition(rPos);
50     SetLookAt(rLookAt);
51     SetFocalLength(fFocalLen);
52 }
53 
54 /*************************************************************************
55 |*
56 |* Default-Konstruktor
57 |*
58 \************************************************************************/
59 
60 Camera3D::Camera3D()
61 {
62     basegfx::B3DPoint aVector3D(0.0 ,0.0 ,1.0);
63     Camera3D(aVector3D, basegfx::B3DPoint());
64 }
65 
66 /*************************************************************************
67 |*
68 |* Konstruktor
69 |*
70 \************************************************************************/
71 
72 void Camera3D::Reset()
73 {
74     SetVPD(0);
75     fBankAngle = fResetBankAngle;
76     SetPosition(aResetPos);
77     SetLookAt(aResetLookAt);
78     SetFocalLength(fResetFocalLength);
79 }
80 
81 /*************************************************************************
82 |*
83 |* Defaultwerte fuer Reset setzen
84 |*
85 \************************************************************************/
86 
87 void Camera3D::SetDefaults(const basegfx::B3DPoint& rPos, const basegfx::B3DPoint& rLookAt,
88                             double fFocalLen, double fBankAng)
89 {
90     aResetPos           = rPos;
91     aResetLookAt        = rLookAt;
92     fResetFocalLength   = fFocalLen;
93     fResetBankAngle     = fBankAng;
94 }
95 
96 /*************************************************************************
97 |*
98 |* ViewWindow setzen und PRP anpassen
99 |*
100 \************************************************************************/
101 
102 void Camera3D::SetViewWindow(double fX, double fY, double fW, double fH)
103 {
104     Viewport3D::SetViewWindow(fX, fY, fW, fH);
105     if ( bAutoAdjustProjection )
106         SetFocalLength(fFocalLength);
107 }
108 
109 /*************************************************************************
110 |*
111 |* Kameraposition setzen
112 |*
113 \************************************************************************/
114 
115 void Camera3D::SetPosition(const basegfx::B3DPoint& rNewPos)
116 {
117     if ( rNewPos != aPosition )
118     {
119         aPosition = rNewPos;
120         SetVRP(aPosition);
121         SetVPN(aPosition - aLookAt);
122         SetBankAngle(fBankAngle);
123     }
124 }
125 
126 /*************************************************************************
127 |*
128 |* Blickpunkt setzen
129 |*
130 \************************************************************************/
131 
132 void Camera3D::SetLookAt(const basegfx::B3DPoint& rNewLookAt)
133 {
134     if ( rNewLookAt != aLookAt )
135     {
136         aLookAt = rNewLookAt;
137         SetVPN(aPosition - aLookAt);
138         SetBankAngle(fBankAngle);
139     }
140 }
141 
142 /*************************************************************************
143 |*
144 |* Position und Blickpunkt setzen
145 |*
146 \************************************************************************/
147 
148 void Camera3D::SetPosAndLookAt(const basegfx::B3DPoint& rNewPos,
149                                const basegfx::B3DPoint& rNewLookAt)
150 {
151     if ( rNewPos != aPosition || rNewLookAt != aLookAt )
152     {
153         aPosition = rNewPos;
154         aLookAt = rNewLookAt;
155 
156         SetVRP(aPosition);
157         SetVPN(aPosition - aLookAt);
158         SetBankAngle(fBankAngle);
159     }
160 }
161 
162 /*************************************************************************
163 |*
164 |* seitlichen Neigungswinkel setzen
165 |*
166 \************************************************************************/
167 
168 void Camera3D::SetBankAngle(double fAngle)
169 {
170     basegfx::B3DVector aDiff(aPosition - aLookAt);
171     basegfx::B3DVector aPrj(aDiff);
172     fBankAngle = fAngle;
173 
174     if ( aDiff.getY() == 0 )
175     {
176         aPrj.setY(-1.0);
177     }
178     else
179     {   // aPrj = Projektion von aDiff auf die XZ-Ebene
180         aPrj.setY(0.0);
181 
182         if ( aDiff.getY() < 0.0 )
183         {
184             aPrj = -aPrj;
185         }
186     }
187 
188     // von aDiff nach oben zeigenden View-Up-Vektor berechnen
189     aPrj = aPrj.getPerpendicular(aDiff);
190     aPrj = aPrj.getPerpendicular(aDiff);
191     aDiff.normalize();
192 
193     // auf Z-Achse rotieren, dort um BankAngle drehen und zurueck
194     basegfx::B3DHomMatrix aTf;
195     const double fV(sqrt(aDiff.getY() * aDiff.getY() + aDiff.getZ() * aDiff.getZ()));
196 
197     if ( fV != 0.0 )
198     {
199         basegfx::B3DHomMatrix aTemp;
200         const double fSin(aDiff.getY() / fV);
201         const double fCos(aDiff.getZ() / fV);
202 
203         aTemp.set(1, 1, fCos);
204         aTemp.set(2, 2, fCos);
205         aTemp.set(2, 1, fSin);
206         aTemp.set(1, 2, -fSin);
207 
208         aTf *= aTemp;
209     }
210 
211     {
212         basegfx::B3DHomMatrix aTemp;
213         const double fSin(-aDiff.getX());
214         const double fCos(fV);
215 
216         aTemp.set(0, 0, fCos);
217         aTemp.set(2, 2, fCos);
218         aTemp.set(0, 2, fSin);
219         aTemp.set(2, 0, -fSin);
220 
221         aTf *= aTemp;
222     }
223 
224     aTf.rotate(0.0, 0.0, fBankAngle);
225 
226     {
227         basegfx::B3DHomMatrix aTemp;
228         const double fSin(aDiff.getX());
229         const double fCos(fV);
230 
231         aTemp.set(0, 0, fCos);
232         aTemp.set(2, 2, fCos);
233         aTemp.set(0, 2, fSin);
234         aTemp.set(2, 0, -fSin);
235 
236         aTf *= aTemp;
237     }
238 
239     if ( fV != 0.0 )
240     {
241         basegfx::B3DHomMatrix aTemp;
242         const double fSin(-aDiff.getY() / fV);
243         const double fCos(aDiff.getZ() / fV);
244 
245         aTemp.set(1, 1, fCos);
246         aTemp.set(2, 2, fCos);
247         aTemp.set(2, 1, fSin);
248         aTemp.set(1, 2, -fSin);
249 
250         aTf *= aTemp;
251     }
252 
253     SetVUV(aTf * aPrj);
254 }
255 
256 /*************************************************************************
257 |*
258 |* Brennweite setzen
259 |*
260 \************************************************************************/
261 
262 void Camera3D::SetFocalLength(double fLen)
263 {
264     if ( fLen < 5 )
265         fLen = 5;
266     SetPRP(basegfx::B3DPoint(0.0, 0.0, fLen / 35.0 * aViewWin.W));
267     fFocalLength = fLen;
268 }
269 
270 /*************************************************************************
271 |*
272 |* Um die Kameraposition drehen, LookAt wird dabei veraendert
273 |*
274 \************************************************************************/
275 
276 void Camera3D::Rotate(double fHAngle, double fVAngle)
277 {
278     basegfx::B3DHomMatrix aTf;
279     basegfx::B3DVector aDiff(aLookAt - aPosition);
280     const double fV(sqrt(aDiff.getX() * aDiff.getX() + aDiff.getZ() * aDiff.getZ()));
281 
282     if ( fV != 0.0 )
283     {
284         basegfx::B3DHomMatrix aTemp;
285         const double fSin(aDiff.getZ() / fV);
286         const double fCos(aDiff.getX() / fV);
287 
288         aTemp.set(0, 0, fCos);
289         aTemp.set(2, 2, fCos);
290         aTemp.set(0, 2, fSin);
291         aTemp.set(2, 0, -fSin);
292 
293         aTf *= aTemp;
294     }
295 
296     {
297         aTf.rotate(0.0, 0.0, fVAngle);
298     }
299 
300     if ( fV != 0.0 )
301     {
302         basegfx::B3DHomMatrix aTemp;
303         const double fSin(-aDiff.getZ() / fV);
304         const double fCos(aDiff.getX() / fV);
305 
306         aTemp.set(0, 0, fCos);
307         aTemp.set(2, 2, fCos);
308         aTemp.set(0, 2, fSin);
309         aTemp.set(2, 0, -fSin);
310 
311         aTf *= aTemp;
312     }
313 
314     {
315         aTf.rotate(0.0, fHAngle, 0.0);
316     }
317 
318     aDiff *= aTf;
319     SetLookAt(aPosition + aDiff);
320 }
321 
322 
323 /*************************************************************************
324 |*
325 |* Um den Blickpunkt drehen, Position wird dabei veraendert
326 |*
327 \************************************************************************/
328 
329 void Camera3D::RotateAroundLookAt(double fHAngle, double fVAngle)
330 {
331     basegfx::B3DHomMatrix aTf;
332     basegfx::B3DVector aDiff(aPosition - aLookAt);
333     const double fV(sqrt(aDiff.getX() * aDiff.getX() + aDiff.getZ() * aDiff.getZ()));
334 
335     if ( fV != 0.0 )
336     {
337         basegfx::B3DHomMatrix aTemp;
338         const double fSin(aDiff.getZ() / fV);
339         const double fCos(aDiff.getX() / fV);
340 
341         aTemp.set(0, 0, fCos);
342         aTemp.set(2, 2, fCos);
343         aTemp.set(0, 2, fSin);
344         aTemp.set(2, 0, -fSin);
345 
346         aTf *= aTemp;
347     }
348 
349     {
350         aTf.rotate(0.0, 0.0, fVAngle);
351     }
352 
353     if ( fV != 0.0 )
354     {
355         basegfx::B3DHomMatrix aTemp;
356         const double fSin(-aDiff.getZ() / fV);
357         const double fCos(aDiff.getX() / fV);
358 
359         aTemp.set(0, 0, fCos);
360         aTemp.set(2, 2, fCos);
361         aTemp.set(0, 2, fSin);
362         aTemp.set(2, 0, -fSin);
363 
364         aTf *= aTemp;
365     }
366 
367     {
368         aTf.rotate(0.0, fHAngle, 0.0);
369     }
370 
371     aDiff *= aTf;
372     SetPosition(aLookAt + aDiff);
373 }
374 
375 /*************************************************************************
376 |*
377 |* FG: ??? Setzt wohl die Projektionsebene in eine bestimmte Tiefe
378 |*
379 \************************************************************************/
380 
381 void Camera3D::SetFocalLengthWithCorrect(double fLen)
382 {
383     if ( fLen < 5.0 )
384     {
385         fLen = 5.0;
386     }
387 
388     SetPRP(basegfx::B3DPoint(0.0, 0.0, aPRP.getZ() * fLen / fFocalLength));
389     fFocalLength = fLen;
390 }
391 
392 // eof
393