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_drawinglayer.hxx" 30 31 #include <drawinglayer/geometry/viewinformation3d.hxx> 32 #include <basegfx/range/b3drange.hxx> 33 #include <basegfx/matrix/b3dhommatrix.hxx> 34 #include <com/sun/star/geometry/AffineMatrix3D.hpp> 35 #include <com/sun/star/geometry/RealRectangle3D.hpp> 36 #include <basegfx/tools/canvastools.hxx> 37 38 ////////////////////////////////////////////////////////////////////////////// 39 40 using namespace com::sun::star; 41 42 ////////////////////////////////////////////////////////////////////////////// 43 44 namespace drawinglayer 45 { 46 namespace geometry 47 { 48 /** Implementation class for ViewInformation3D 49 */ 50 class ImpViewInformation3D 51 { 52 private: 53 // ViewInformation3D implementation can change refcount, so we have only 54 // two memory regions for pairs of ViewInformation3D/ImpViewInformation3D 55 friend class ::drawinglayer::geometry::ViewInformation3D; 56 57 // the refcounter. 0 means exclusively used 58 sal_uInt32 mnRefCount; 59 60 // the 3D transformations 61 // Object to World. This may change and being adapted when entering 3D transformation 62 // groups 63 basegfx::B3DHomMatrix maObjectTransformation; 64 65 // World to Camera. This includes VRP, VPN and VUV camera coordinate system 66 basegfx::B3DHomMatrix maOrientation; 67 68 // Camera to Device with X,Y and Z [-1.0 .. 1.0]. This is the 69 // 3D to 2D projection which may be parallell or perspective. When it is perspective, 70 // the last line of the homogen matrix will NOT be unused 71 basegfx::B3DHomMatrix maProjection; 72 73 // Device to View with X,Y and Z [0.0 .. 1.0]. This converts from -1 to 1 coordinates 74 // in camera coordinate system to 0 to 1 in unit 2D coordinates. This way it stays 75 // view-independent. To get discrete coordinates, the 2D transformation of a scene 76 // as 2D object needs to be involved 77 basegfx::B3DHomMatrix maDeviceToView; 78 79 // Object to View is the linear combination of all four transformations. It's 80 // buffered to avoid too much matrix multiplying and created on demand 81 basegfx::B3DHomMatrix maObjectToView; 82 83 // the point in time 84 double mfViewTime; 85 86 // the complete PropertyValue representation (if already created) 87 uno::Sequence< beans::PropertyValue > mxViewInformation; 88 89 // the extra PropertyValues; does not contain the transformations 90 uno::Sequence< beans::PropertyValue > mxExtendedInformation; 91 92 // the local UNO API strings 93 const ::rtl::OUString& getNamePropertyObjectTransformation() 94 { 95 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ObjectTransformation")); 96 return s_sNameProperty; 97 } 98 99 const ::rtl::OUString& getNamePropertyOrientation() 100 { 101 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Orientation")); 102 return s_sNameProperty; 103 } 104 105 const ::rtl::OUString& getNamePropertyProjection() 106 { 107 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection")); 108 return s_sNameProperty; 109 } 110 111 const ::rtl::OUString& getNamePropertyProjection_30() 112 { 113 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection30")); 114 return s_sNameProperty; 115 } 116 117 const ::rtl::OUString& getNamePropertyProjection_31() 118 { 119 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection31")); 120 return s_sNameProperty; 121 } 122 123 const ::rtl::OUString& getNamePropertyProjection_32() 124 { 125 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection32")); 126 return s_sNameProperty; 127 } 128 129 const ::rtl::OUString& getNamePropertyProjection_33() 130 { 131 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection33")); 132 return s_sNameProperty; 133 } 134 135 const ::rtl::OUString& getNamePropertyDeviceToView() 136 { 137 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("DeviceToView")); 138 return s_sNameProperty; 139 } 140 141 const ::rtl::OUString& getNamePropertyTime() 142 { 143 static ::rtl::OUString s_sNamePropertyTime(RTL_CONSTASCII_USTRINGPARAM("Time")); 144 return s_sNamePropertyTime; 145 } 146 147 // a central PropertyValue parsing method to allow transportatin of 148 // all ViewParameters using UNO API 149 void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters) 150 { 151 if(rViewParameters.hasElements()) 152 { 153 const sal_Int32 nCount(rViewParameters.getLength()); 154 sal_Int32 nExtendedInsert(0); 155 156 // prepare extended information for filtering. Maximum size is nCount 157 mxExtendedInformation.realloc(nCount); 158 159 for(sal_Int32 a(0); a < nCount; a++) 160 { 161 const beans::PropertyValue& rProp = rViewParameters[a]; 162 163 if(rProp.Name == getNamePropertyObjectTransformation()) 164 { 165 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 166 rProp.Value >>= aAffineMatrix3D; 167 maObjectTransformation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); 168 } 169 else if(rProp.Name == getNamePropertyOrientation()) 170 { 171 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 172 rProp.Value >>= aAffineMatrix3D; 173 maOrientation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); 174 } 175 else if(rProp.Name == getNamePropertyProjection()) 176 { 177 // projection may be defined using a frustum in which case the last line of 178 // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that, 179 // these four values need to be treated extra 180 const double f_30(maProjection.get(3, 0)); 181 const double f_31(maProjection.get(3, 1)); 182 const double f_32(maProjection.get(3, 2)); 183 const double f_33(maProjection.get(3, 3)); 184 185 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 186 rProp.Value >>= aAffineMatrix3D; 187 maProjection = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); 188 189 maProjection.set(3, 0, f_30); 190 maProjection.set(3, 1, f_31); 191 maProjection.set(3, 2, f_32); 192 maProjection.set(3, 3, f_33); 193 } 194 else if(rProp.Name == getNamePropertyProjection_30()) 195 { 196 double f_30(0.0); 197 rProp.Value >>= f_30; 198 maProjection.set(3, 0, f_30); 199 } 200 else if(rProp.Name == getNamePropertyProjection_31()) 201 { 202 double f_31(0.0); 203 rProp.Value >>= f_31; 204 maProjection.set(3, 1, f_31); 205 } 206 else if(rProp.Name == getNamePropertyProjection_32()) 207 { 208 double f_32(0.0); 209 rProp.Value >>= f_32; 210 maProjection.set(3, 2, f_32); 211 } 212 else if(rProp.Name == getNamePropertyProjection_33()) 213 { 214 double f_33(1.0); 215 rProp.Value >>= f_33; 216 maProjection.set(3, 3, f_33); 217 } 218 else if(rProp.Name == getNamePropertyDeviceToView()) 219 { 220 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 221 rProp.Value >>= aAffineMatrix3D; 222 maDeviceToView = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); 223 } 224 else if(rProp.Name == getNamePropertyTime()) 225 { 226 rProp.Value >>= mfViewTime; 227 } 228 else 229 { 230 // extra information; add to filtered information 231 mxExtendedInformation[nExtendedInsert++] = rProp; 232 } 233 } 234 235 // extra information size is now known; realloc to final size 236 mxExtendedInformation.realloc(nExtendedInsert); 237 } 238 } 239 240 // central method to create a Sequence of PropertyValues containing he complete 241 // data set 242 void impFillViewInformationFromContent() 243 { 244 uno::Sequence< beans::PropertyValue > xRetval; 245 const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity()); 246 const bool bOrientationUsed(!maOrientation.isIdentity()); 247 const bool bProjectionUsed(!maProjection.isIdentity()); 248 const bool bDeviceToViewUsed(!maDeviceToView.isIdentity()); 249 const bool bTimeUsed(0.0 < mfViewTime); 250 const bool bExtraInformation(mxExtendedInformation.hasElements()); 251 252 // projection may be defined using a frustum in which case the last line of 253 // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that, 254 // these four values need to be treated extra 255 const bool bProjectionUsed_30(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 0))); 256 const bool bProjectionUsed_31(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 1))); 257 const bool bProjectionUsed_32(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 2))); 258 const bool bProjectionUsed_33(bProjectionUsed && !basegfx::fTools::equal(maProjection.get(3, 3), 1.0)); 259 260 sal_uInt32 nIndex(0); 261 const sal_uInt32 nCount( 262 (bObjectTransformationUsed ? 1 : 0) + 263 (bOrientationUsed ? 1 : 0) + 264 (bProjectionUsed ? 1 : 0) + 265 (bProjectionUsed_30 ? 1 : 0) + 266 (bProjectionUsed_31 ? 1 : 0) + 267 (bProjectionUsed_32 ? 1 : 0) + 268 (bProjectionUsed_33 ? 1 : 0) + 269 (bDeviceToViewUsed ? 1 : 0) + 270 (bTimeUsed ? 1 : 0) + 271 (bExtraInformation ? mxExtendedInformation.getLength() : 0)); 272 273 mxViewInformation.realloc(nCount); 274 275 if(bObjectTransformationUsed) 276 { 277 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 278 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maObjectTransformation); 279 mxViewInformation[nIndex].Name = getNamePropertyObjectTransformation(); 280 mxViewInformation[nIndex].Value <<= aAffineMatrix3D; 281 nIndex++; 282 } 283 284 if(bOrientationUsed) 285 { 286 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 287 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maOrientation); 288 mxViewInformation[nIndex].Name = getNamePropertyOrientation(); 289 mxViewInformation[nIndex].Value <<= aAffineMatrix3D; 290 nIndex++; 291 } 292 293 if(bProjectionUsed) 294 { 295 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 296 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maProjection); 297 mxViewInformation[nIndex].Name = getNamePropertyProjection(); 298 mxViewInformation[nIndex].Value <<= aAffineMatrix3D; 299 nIndex++; 300 } 301 302 if(bProjectionUsed_30) 303 { 304 mxViewInformation[nIndex].Name = getNamePropertyProjection_30(); 305 mxViewInformation[nIndex].Value <<= maProjection.get(3, 0); 306 nIndex++; 307 } 308 309 if(bProjectionUsed_31) 310 { 311 mxViewInformation[nIndex].Name = getNamePropertyProjection_31(); 312 mxViewInformation[nIndex].Value <<= maProjection.get(3, 1); 313 nIndex++; 314 } 315 316 if(bProjectionUsed_32) 317 { 318 mxViewInformation[nIndex].Name = getNamePropertyProjection_32(); 319 mxViewInformation[nIndex].Value <<= maProjection.get(3, 2); 320 nIndex++; 321 } 322 323 if(bProjectionUsed_33) 324 { 325 mxViewInformation[nIndex].Name = getNamePropertyProjection_33(); 326 mxViewInformation[nIndex].Value <<= maProjection.get(3, 3); 327 nIndex++; 328 } 329 330 if(bDeviceToViewUsed) 331 { 332 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 333 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maDeviceToView); 334 mxViewInformation[nIndex].Name = getNamePropertyDeviceToView(); 335 mxViewInformation[nIndex].Value <<= aAffineMatrix3D; 336 nIndex++; 337 } 338 339 if(bTimeUsed) 340 { 341 mxViewInformation[nIndex].Name = getNamePropertyTime(); 342 mxViewInformation[nIndex].Value <<= mfViewTime; 343 nIndex++; 344 } 345 346 if(bExtraInformation) 347 { 348 const sal_Int32 nExtra(mxExtendedInformation.getLength()); 349 350 for(sal_Int32 a(0); a < nExtra; a++) 351 { 352 mxViewInformation[nIndex++] = mxExtendedInformation[a]; 353 } 354 } 355 } 356 357 public: 358 ImpViewInformation3D( 359 const basegfx::B3DHomMatrix& rObjectTransformation, 360 const basegfx::B3DHomMatrix& rOrientation, 361 const basegfx::B3DHomMatrix& rProjection, 362 const basegfx::B3DHomMatrix& rDeviceToView, 363 double fViewTime, 364 const uno::Sequence< beans::PropertyValue >& rExtendedParameters) 365 : mnRefCount(0), 366 maObjectTransformation(rObjectTransformation), 367 maOrientation(rOrientation), 368 maProjection(rProjection), 369 maDeviceToView(rDeviceToView), 370 mfViewTime(fViewTime), 371 mxViewInformation(), 372 mxExtendedInformation() 373 { 374 impInterpretPropertyValues(rExtendedParameters); 375 } 376 377 ImpViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters) 378 : mnRefCount(0), 379 maObjectTransformation(), 380 maOrientation(), 381 maProjection(), 382 maDeviceToView(), 383 mfViewTime(), 384 mxViewInformation(rViewParameters), 385 mxExtendedInformation() 386 { 387 impInterpretPropertyValues(rViewParameters); 388 } 389 390 ImpViewInformation3D() 391 : mnRefCount(0), 392 maObjectTransformation(), 393 maOrientation(), 394 maProjection(), 395 maDeviceToView(), 396 mfViewTime(), 397 mxViewInformation(), 398 mxExtendedInformation() 399 { 400 } 401 402 const basegfx::B3DHomMatrix& getObjectTransformation() const { return maObjectTransformation; } 403 const basegfx::B3DHomMatrix& getOrientation() const { return maOrientation; } 404 const basegfx::B3DHomMatrix& getProjection() const { return maProjection; } 405 const basegfx::B3DHomMatrix& getDeviceToView() const { return maDeviceToView; } 406 double getViewTime() const { return mfViewTime; } 407 408 const basegfx::B3DHomMatrix& getObjectToView() const 409 { 410 // on demand WorldToView creation 411 ::osl::Mutex m_mutex; 412 413 if(maObjectToView.isIdentity()) 414 { 415 const_cast< ImpViewInformation3D* >(this)->maObjectToView = maDeviceToView * maProjection * maOrientation * maObjectTransformation; 416 } 417 418 return maObjectToView; 419 } 420 421 const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const 422 { 423 ::osl::Mutex m_mutex; 424 425 if(!mxViewInformation.hasElements()) 426 { 427 const_cast< ImpViewInformation3D* >(this)->impFillViewInformationFromContent(); 428 } 429 430 return mxViewInformation; 431 } 432 433 const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const 434 { 435 return mxExtendedInformation; 436 } 437 438 bool operator==(const ImpViewInformation3D& rCandidate) const 439 { 440 return (maObjectTransformation == rCandidate.maObjectTransformation 441 && maOrientation == rCandidate.maOrientation 442 && maProjection == rCandidate.maProjection 443 && maDeviceToView == rCandidate.maDeviceToView 444 && mfViewTime == rCandidate.mfViewTime 445 && mxExtendedInformation == rCandidate.mxExtendedInformation); 446 } 447 448 static ImpViewInformation3D* get_global_default() 449 { 450 static ImpViewInformation3D* pDefault = 0; 451 452 if(!pDefault) 453 { 454 pDefault = new ImpViewInformation3D(); 455 456 // never delete; start with RefCount 1, not 0 457 pDefault->mnRefCount++; 458 } 459 460 return pDefault; 461 } 462 }; 463 } // end of anonymous namespace 464 } // end of namespace drawinglayer 465 466 ////////////////////////////////////////////////////////////////////////////// 467 468 namespace drawinglayer 469 { 470 namespace geometry 471 { 472 ViewInformation3D::ViewInformation3D( 473 const basegfx::B3DHomMatrix& rObjectObjectTransformation, 474 const basegfx::B3DHomMatrix& rOrientation, 475 const basegfx::B3DHomMatrix& rProjection, 476 const basegfx::B3DHomMatrix& rDeviceToView, 477 double fViewTime, 478 const uno::Sequence< beans::PropertyValue >& rExtendedParameters) 479 : mpViewInformation3D(new ImpViewInformation3D( 480 rObjectObjectTransformation, rOrientation, rProjection, 481 rDeviceToView, fViewTime, rExtendedParameters)) 482 { 483 } 484 485 ViewInformation3D::ViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters) 486 : mpViewInformation3D(new ImpViewInformation3D(rViewParameters)) 487 { 488 } 489 490 ViewInformation3D::ViewInformation3D() 491 : mpViewInformation3D(ImpViewInformation3D::get_global_default()) 492 { 493 mpViewInformation3D->mnRefCount++; 494 } 495 496 ViewInformation3D::ViewInformation3D(const ViewInformation3D& rCandidate) 497 : mpViewInformation3D(rCandidate.mpViewInformation3D) 498 { 499 ::osl::Mutex m_mutex; 500 mpViewInformation3D->mnRefCount++; 501 } 502 503 ViewInformation3D::~ViewInformation3D() 504 { 505 ::osl::Mutex m_mutex; 506 507 if(mpViewInformation3D->mnRefCount) 508 { 509 mpViewInformation3D->mnRefCount--; 510 } 511 else 512 { 513 delete mpViewInformation3D; 514 } 515 } 516 517 bool ViewInformation3D::isDefault() const 518 { 519 return mpViewInformation3D == ImpViewInformation3D::get_global_default(); 520 } 521 522 ViewInformation3D& ViewInformation3D::operator=(const ViewInformation3D& rCandidate) 523 { 524 ::osl::Mutex m_mutex; 525 526 if(mpViewInformation3D->mnRefCount) 527 { 528 mpViewInformation3D->mnRefCount--; 529 } 530 else 531 { 532 delete mpViewInformation3D; 533 } 534 535 mpViewInformation3D = rCandidate.mpViewInformation3D; 536 mpViewInformation3D->mnRefCount++; 537 538 return *this; 539 } 540 541 bool ViewInformation3D::operator==(const ViewInformation3D& rCandidate) const 542 { 543 if(rCandidate.mpViewInformation3D == mpViewInformation3D) 544 { 545 return true; 546 } 547 548 if(rCandidate.isDefault() != isDefault()) 549 { 550 return false; 551 } 552 553 return (*rCandidate.mpViewInformation3D == *mpViewInformation3D); 554 } 555 556 const basegfx::B3DHomMatrix& ViewInformation3D::getObjectTransformation() const 557 { 558 return mpViewInformation3D->getObjectTransformation(); 559 } 560 561 const basegfx::B3DHomMatrix& ViewInformation3D::getOrientation() const 562 { 563 return mpViewInformation3D->getOrientation(); 564 } 565 566 const basegfx::B3DHomMatrix& ViewInformation3D::getProjection() const 567 { 568 return mpViewInformation3D->getProjection(); 569 } 570 571 const basegfx::B3DHomMatrix& ViewInformation3D::getDeviceToView() const 572 { 573 return mpViewInformation3D->getDeviceToView(); 574 } 575 576 const basegfx::B3DHomMatrix& ViewInformation3D::getObjectToView() const 577 { 578 return mpViewInformation3D->getObjectToView(); 579 } 580 581 double ViewInformation3D::getViewTime() const 582 { 583 return mpViewInformation3D->getViewTime(); 584 } 585 586 const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getViewInformationSequence() const 587 { 588 return mpViewInformation3D->getViewInformationSequence(); 589 } 590 591 const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getExtendedInformationSequence() const 592 { 593 return mpViewInformation3D->getExtendedInformationSequence(); 594 } 595 } // end of namespace geometry 596 } // end of namespace drawinglayer 597 598 ////////////////////////////////////////////////////////////////////////////// 599 // eof 600