xref: /aoo41x/main/svx/source/engine3d/camera3d.cxx (revision cdf0e10c)
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