1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: zbufferprocessor3d.cxx,v $
9 * last change: $Author: aw $ $Date: 2008-06-24 15:31:09 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
34 ************************************************************************/
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_drawinglayer.hxx"
39 #include <drawinglayer/processor3d/zbufferprocessor3d.hxx>
40 #include <basegfx/raster/bpixelraster.hxx>
41 #include <vcl/bmpacc.hxx>
42 #include <basegfx/raster/rasterconvert3d.hxx>
43 #include <basegfx/raster/bzpixelraster.hxx>
44 #include <drawinglayer/attribute/materialattribute3d.hxx>
45 #include <drawinglayer/texture/texture.hxx>
46 #include <drawinglayer/attribute/sdrattribute3d.hxx>
47 #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
48 #include <drawinglayer/primitive3d/textureprimitive3d.hxx>
49 #include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
50 #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
51 #include <drawinglayer/geometry/viewinformation2d.hxx>
52 #include <basegfx/polygon/b3dpolygontools.hxx>
54 //////////////////////////////////////////////////////////////////////////////
56 using namespace com::sun::star
;
58 //////////////////////////////////////////////////////////////////////////////
62 BitmapEx
BPixelRasterToBitmapEx(const basegfx::BPixelRaster
& rRaster
, sal_uInt16 mnAntiAlialize
)
65 const sal_uInt32
nWidth(mnAntiAlialize
? rRaster
.getWidth()/mnAntiAlialize
: rRaster
.getWidth());
66 const sal_uInt32
nHeight(mnAntiAlialize
? rRaster
.getHeight()/mnAntiAlialize
: rRaster
.getHeight());
70 const Size
aDestSize(nWidth
, nHeight
);
71 sal_uInt8
nInitAlpha(255);
72 Bitmap
aContent(aDestSize
, 24);
73 AlphaMask
aAlpha(aDestSize
, &nInitAlpha
);
74 BitmapWriteAccess
* pContent
= aContent
.AcquireWriteAccess();
75 BitmapWriteAccess
* pAlpha
= aAlpha
.AcquireWriteAccess();
77 if(pContent
&& pAlpha
)
81 const sal_uInt16
nDivisor(mnAntiAlialize
* mnAntiAlialize
);
83 for(sal_uInt32
y(0L); y
< nHeight
; y
++)
85 for(sal_uInt32
x(0L); x
< nWidth
; x
++)
90 sal_uInt16
nOpacity(0);
91 sal_uInt32
nIndex(rRaster
.getIndexFromXY(x
* mnAntiAlialize
, y
* mnAntiAlialize
));
93 for(sal_uInt32
c(0); c
< mnAntiAlialize
; c
++)
95 for(sal_uInt32
d(0); d
< mnAntiAlialize
; d
++)
97 const basegfx::BPixel
& rPixel(rRaster
.getBPixel(nIndex
++));
98 nRed
= nRed
+ rPixel
.getRed();
99 nGreen
= nGreen
+ rPixel
.getGreen();
100 nBlue
= nBlue
+ rPixel
.getBlue();
101 nOpacity
= nOpacity
+ rPixel
.getOpacity();
104 nIndex
+= rRaster
.getWidth() - mnAntiAlialize
;
107 nOpacity
= nOpacity
/ nDivisor
;
111 pContent
->SetPixel(y
, x
, BitmapColor(
112 (sal_uInt8
)(nRed
/ nDivisor
),
113 (sal_uInt8
)(nGreen
/ nDivisor
),
114 (sal_uInt8
)(nBlue
/ nDivisor
)));
115 pAlpha
->SetPixel(y
, x
, BitmapColor(255 - (sal_uInt8
)nOpacity
));
122 sal_uInt32
nIndex(0L);
124 for(sal_uInt32
y(0L); y
< nHeight
; y
++)
126 for(sal_uInt32
x(0L); x
< nWidth
; x
++)
128 const basegfx::BPixel
& rPixel(rRaster
.getBPixel(nIndex
++));
130 if(rPixel
.getOpacity())
132 pContent
->SetPixel(y
, x
, BitmapColor(rPixel
.getRed(), rPixel
.getGreen(), rPixel
.getBlue()));
133 pAlpha
->SetPixel(y
, x
, BitmapColor(255 - rPixel
.getOpacity()));
143 aRetval
= BitmapEx(aContent
, aAlpha
);
145 // #i101811# set PrefMapMode and PrefSize at newly created Bitmap
146 aRetval
.SetPrefMapMode(MAP_100TH_MM
);
147 aRetval
.SetPrefSize(Size(nWidth
, nHeight
));
152 } // end of anonymous namespace
154 //////////////////////////////////////////////////////////////////////////////
156 class ZBufferRasterConverter3D
: public basegfx::RasterConverter3D
159 const drawinglayer::processor3d::DefaultProcessor3D
& mrProcessor
;
160 basegfx::BZPixelRaster
& mrBuffer
;
162 // interpolators for a single line span
163 basegfx::ip_single maIntZ
;
164 basegfx::ip_triple maIntColor
;
165 basegfx::ip_triple maIntNormal
;
166 basegfx::ip_double maIntTexture
;
167 basegfx::ip_triple maIntInvTexture
;
169 // current material to use for ratsreconversion
170 const drawinglayer::attribute::MaterialAttribute3D
* mpCurrentMaterial
;
173 // some boolean flags for line span interpolator usages
174 unsigned mbModifyColor
: 1;
175 unsigned mbUseTex
: 1;
176 unsigned mbHasTexCoor
: 1;
177 unsigned mbHasInvTexCoor
: 1;
178 unsigned mbUseNrm
: 1;
179 unsigned mbUseCol
: 1;
181 void getTextureCoor(basegfx::B2DPoint
& rTarget
) const
185 rTarget
.setX(maIntTexture
.getX().getVal());
186 rTarget
.setY(maIntTexture
.getY().getVal());
188 else if(mbHasInvTexCoor
)
190 const double fZFactor(maIntInvTexture
.getZ().getVal());
191 const double fInvZFactor(basegfx::fTools::equalZero(fZFactor
) ? 1.0 : 1.0 / fZFactor
);
192 rTarget
.setX(maIntInvTexture
.getX().getVal() * fInvZFactor
);
193 rTarget
.setY(maIntInvTexture
.getY().getVal() * fInvZFactor
);
197 void incrementLineSpanInterpolators(double fStep
)
199 maIntZ
.increment(fStep
);
205 maIntTexture
.increment(fStep
);
207 else if(mbHasInvTexCoor
)
209 maIntInvTexture
.increment(fStep
);
215 maIntNormal
.increment(fStep
);
220 maIntColor
.increment(fStep
);
224 double decideColorAndOpacity(basegfx::BColor
& rColor
)
226 // init values with full opacity and material color
227 OSL_ENSURE(0 != mpCurrentMaterial
, "CurrentMaterial not set (!)");
228 double fOpacity(1.0);
229 rColor
= mpCurrentMaterial
->getColor();
233 basegfx::B2DPoint
aTexCoor(0.0, 0.0);
234 getTextureCoor(aTexCoor
);
236 if(mrProcessor
.getGeoTexSvx())
238 // calc color in spot. This may also set to invisible already when
239 // e.g. bitmap textures have transparent parts
240 mrProcessor
.getGeoTexSvx()->modifyBColor(aTexCoor
, rColor
, fOpacity
);
243 if(basegfx::fTools::more(fOpacity
, 0.0) && mrProcessor
.getTransparenceGeoTexSvx())
245 // calc opacity. Object has a 2nd texture, a transparence texture
246 mrProcessor
.getTransparenceGeoTexSvx()->modifyOpacity(aTexCoor
, fOpacity
);
250 if(basegfx::fTools::more(fOpacity
, 0.0))
252 if(mrProcessor
.getGeoTexSvx())
256 // blend texture with phong
257 rColor
= mrProcessor
.getSdrLightingAttribute().solveColorModel(
258 basegfx::B3DVector(maIntNormal
.getX().getVal(), maIntNormal
.getY().getVal(), maIntNormal
.getZ().getVal()),
260 mpCurrentMaterial
->getSpecular(),
261 mpCurrentMaterial
->getEmission(),
262 mpCurrentMaterial
->getSpecularIntensity());
266 // blend texture with gouraud
267 basegfx::BColor
aBlendColor(maIntColor
.getX().getVal(), maIntColor
.getY().getVal(), maIntColor
.getZ().getVal());
268 rColor
*= aBlendColor
;
270 else if(mrProcessor
.getModulate())
272 // blend texture with single material color
273 rColor
*= mpCurrentMaterial
->getColor();
280 // modify color with phong
281 rColor
= mrProcessor
.getSdrLightingAttribute().solveColorModel(
282 basegfx::B3DVector(maIntNormal
.getX().getVal(), maIntNormal
.getY().getVal(), maIntNormal
.getZ().getVal()),
284 mpCurrentMaterial
->getSpecular(),
285 mpCurrentMaterial
->getEmission(),
286 mpCurrentMaterial
->getSpecularIntensity());
290 // modify color with gouraud
291 rColor
.setRed(maIntColor
.getX().getVal());
292 rColor
.setGreen(maIntColor
.getY().getVal());
293 rColor
.setBlue(maIntColor
.getZ().getVal());
299 rColor
= mrProcessor
.getBColorModifierStack().getModifiedColor(rColor
);
306 void setupLineSpanInterpolators(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
)
308 // get inverse XDelta
309 const double xInvDelta(1.0 / (rB
.getX().getVal() - rA
.getX().getVal()));
311 // prepare Z-interpolator
312 const double fZA(rA
.getZ().getVal());
313 const double fZB(rB
.getZ().getVal());
314 maIntZ
= basegfx::ip_single(fZA
, (fZB
- fZA
) * xInvDelta
);
316 // get bools and init other interpolators on demand accordingly
317 mbModifyColor
= mrProcessor
.getBColorModifierStack().count();
318 mbHasTexCoor
= SCANLINE_EMPTY_INDEX
!= rA
.getTextureIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getTextureIndex();
319 mbHasInvTexCoor
= SCANLINE_EMPTY_INDEX
!= rA
.getInverseTextureIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getInverseTextureIndex();
320 const bool bTextureActive(mrProcessor
.getGeoTexSvx() || mrProcessor
.getTransparenceGeoTexSvx());
321 mbUseTex
= bTextureActive
&& (mbHasTexCoor
|| mbHasInvTexCoor
|| mrProcessor
.getSimpleTextureActive());
322 const bool bUseColorTex(mbUseTex
&& mrProcessor
.getGeoTexSvx());
323 const bool bNeedNrmOrCol(!bUseColorTex
|| (bUseColorTex
&& mrProcessor
.getModulate()));
324 mbUseNrm
= bNeedNrmOrCol
&& SCANLINE_EMPTY_INDEX
!= rA
.getNormalIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getNormalIndex();
325 mbUseCol
= !mbUseNrm
&& bNeedNrmOrCol
&& SCANLINE_EMPTY_INDEX
!= rA
.getColorIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getColorIndex();
331 const basegfx::ip_double
& rTA(getTextureInterpolators()[rA
.getTextureIndex()]);
332 const basegfx::ip_double
& rTB(getTextureInterpolators()[rB
.getTextureIndex()]);
333 maIntTexture
= basegfx::ip_double(
334 rTA
.getX().getVal(), (rTB
.getX().getVal() - rTA
.getX().getVal()) * xInvDelta
,
335 rTA
.getY().getVal(), (rTB
.getY().getVal() - rTA
.getY().getVal()) * xInvDelta
);
337 else if(mbHasInvTexCoor
)
339 const basegfx::ip_triple
& rITA(getInverseTextureInterpolators()[rA
.getInverseTextureIndex()]);
340 const basegfx::ip_triple
& rITB(getInverseTextureInterpolators()[rB
.getInverseTextureIndex()]);
341 maIntInvTexture
= basegfx::ip_triple(
342 rITA
.getX().getVal(), (rITB
.getX().getVal() - rITA
.getX().getVal()) * xInvDelta
,
343 rITA
.getY().getVal(), (rITB
.getY().getVal() - rITA
.getY().getVal()) * xInvDelta
,
344 rITA
.getZ().getVal(), (rITB
.getZ().getVal() - rITA
.getZ().getVal()) * xInvDelta
);
350 const basegfx::ip_triple
& rNA(getNormalInterpolators()[rA
.getNormalIndex()]);
351 const basegfx::ip_triple
& rNB(getNormalInterpolators()[rB
.getNormalIndex()]);
352 maIntNormal
= basegfx::ip_triple(
353 rNA
.getX().getVal(), (rNB
.getX().getVal() - rNA
.getX().getVal()) * xInvDelta
,
354 rNA
.getY().getVal(), (rNB
.getY().getVal() - rNA
.getY().getVal()) * xInvDelta
,
355 rNA
.getZ().getVal(), (rNB
.getZ().getVal() - rNA
.getZ().getVal()) * xInvDelta
);
360 const basegfx::ip_triple
& rCA(getColorInterpolators()[rA
.getColorIndex()]);
361 const basegfx::ip_triple
& rCB(getColorInterpolators()[rB
.getColorIndex()]);
362 maIntColor
= basegfx::ip_triple(
363 rCA
.getX().getVal(), (rCB
.getX().getVal() - rCA
.getX().getVal()) * xInvDelta
,
364 rCA
.getY().getVal(), (rCB
.getY().getVal() - rCA
.getY().getVal()) * xInvDelta
,
365 rCA
.getZ().getVal(), (rCB
.getZ().getVal() - rCA
.getZ().getVal()) * xInvDelta
);
369 virtual void processLineSpan(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
, sal_Int32 nLine
, sal_uInt32 nSpanCount
);
372 ZBufferRasterConverter3D(basegfx::BZPixelRaster
& rBuffer
, const drawinglayer::processor3d::ZBufferProcessor3D
& rProcessor
)
373 : basegfx::RasterConverter3D(),
374 mrProcessor(rProcessor
),
381 mpCurrentMaterial(0),
382 mbModifyColor(false),
389 void setCurrentMaterial(const drawinglayer::attribute::MaterialAttribute3D
& rMaterial
)
391 mpCurrentMaterial
= &rMaterial
;
395 void ZBufferRasterConverter3D::processLineSpan(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
, sal_Int32 nLine
, sal_uInt32 nSpanCount
)
397 if(!(nSpanCount
& 0x0001))
399 if(nLine
>= 0 && nLine
< (sal_Int32
)mrBuffer
.getHeight())
401 sal_uInt32
nXA(::std::min(mrBuffer
.getWidth(), (sal_uInt32
)::std::max((sal_Int32
)0, basegfx::fround(rA
.getX().getVal()))));
402 const sal_uInt32
nXB(::std::min(mrBuffer
.getWidth(), (sal_uInt32
)::std::max((sal_Int32
)0, basegfx::fround(rB
.getX().getVal()))));
406 // prepare the span interpolators
407 setupLineSpanInterpolators(rA
, rB
);
409 // bring span interpolators to start condition by incrementing with the possible difference of
410 // clamped and non-clamped XStart. Interpolators are setup relying on double precision
411 // X-values, so that difference is the correct value to compensate for possible clampings
412 incrementLineSpanInterpolators(static_cast<double>(nXA
) - rA
.getX().getVal());
414 // prepare scanline index
415 sal_uInt32
nScanlineIndex(mrBuffer
.getIndexFromXY(nXA
, static_cast<sal_uInt32
>(nLine
)));
416 basegfx::BColor aNewColor
;
420 // early-test Z values if we need to do anything at all
421 const double fNewZ(::std::max(0.0, ::std::min((double)0xffff, maIntZ
.getVal())));
422 const sal_uInt16
nNewZ(static_cast< sal_uInt16
>(fNewZ
));
423 sal_uInt16
& rOldZ(mrBuffer
.getZ(nScanlineIndex
));
427 // detect color and opacity for this pixel
428 const sal_uInt16
nOpacity(::std::max((sal_Int16
)0, static_cast< sal_Int16
>(decideColorAndOpacity(aNewColor
) * 255.0)));
432 // avoid color overrun
435 if(nOpacity
>= 0x00ff)
437 // full opacity, set z and color
439 mrBuffer
.getBPixel(nScanlineIndex
) = basegfx::BPixel(aNewColor
, 0xff);
443 basegfx::BPixel
& rDest
= mrBuffer
.getBPixel(nScanlineIndex
);
445 if(rDest
.getOpacity())
447 // both transparent, mix color based on front pixel's opacity
449 const sal_uInt16
nTransparence(0x0100 - nOpacity
);
450 rDest
.setRed((sal_uInt8
)(((rDest
.getRed() * nTransparence
) + ((sal_uInt16
)(255.0 * aNewColor
.getRed()) * nOpacity
)) >> 8));
451 rDest
.setGreen((sal_uInt8
)(((rDest
.getGreen() * nTransparence
) + ((sal_uInt16
)(255.0 * aNewColor
.getGreen()) * nOpacity
)) >> 8));
452 rDest
.setBlue((sal_uInt8
)(((rDest
.getBlue() * nTransparence
) + ((sal_uInt16
)(255.0 * aNewColor
.getBlue()) * nOpacity
)) >> 8));
454 if(0xff != rDest
.getOpacity())
456 // destination is also transparent, mix opacities by weighting
457 // old opacity with new pixel's transparence and adding new opacity
458 rDest
.setOpacity((sal_uInt8
)(((rDest
.getOpacity() * nTransparence
) >> 8) + nOpacity
));
463 // dest is not visible. Set color.
464 rDest
= basegfx::BPixel(aNewColor
, (sal_uInt8
)nOpacity
);
473 incrementLineSpanInterpolators(1.0);
480 //////////////////////////////////////////////////////////////////////////////
482 namespace drawinglayer
484 namespace processor3d
486 // the processing method for a single, known primitive
487 void ZBufferProcessor3D::processBasePrimitive3D(const primitive3d::BasePrimitive3D
& rBasePrimitive
)
489 // it is a BasePrimitive3D implementation, use getPrimitiveID() call for switch
490 switch(rBasePrimitive
.getPrimitiveID())
492 case PRIMITIVE3D_ID_ALPHATEXTUREPRIMITIVE3D
:
494 // AlphaTexturePrimitive3D
495 const primitive3d::AlphaTexturePrimitive3D
& rPrimitive
= static_cast< const primitive3d::AlphaTexturePrimitive3D
& >(rBasePrimitive
);
497 if(mbProcessTransparent
)
499 impRenderGradientTexturePrimitive3D(rPrimitive
, true);
503 mbContainsTransparent
= true;
507 case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D
:
509 // directdraw of PolygonHairlinePrimitive3D
510 const primitive3d::PolygonHairlinePrimitive3D
& rPrimitive
= static_cast< const primitive3d::PolygonHairlinePrimitive3D
& >(rBasePrimitive
);
512 // do something when either not transparent and no transMap, or transparent and a TransMap
513 if((bool)mbProcessTransparent
== (0 != getTransparenceGeoTexSvx()))
515 impRenderPolygonHairlinePrimitive3D(rPrimitive
);
519 case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D
:
521 // directdraw of PolyPolygonMaterialPrimitive3D
522 const primitive3d::PolyPolygonMaterialPrimitive3D
& rPrimitive
= static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D
& >(rBasePrimitive
);
524 // do something when either not transparent and no transMap, or transparent and a TransMap
525 if((bool)mbProcessTransparent
== (0 != getTransparenceGeoTexSvx()))
527 impRenderPolyPolygonMaterialPrimitive3D(rPrimitive
);
533 // use the DefaultProcessor3D::processBasePrimitive3D()
534 DefaultProcessor3D::processBasePrimitive3D(rBasePrimitive
);
540 void ZBufferProcessor3D::processNonTransparent(const primitive3d::Primitive3DSequence
& rSource
)
544 mbProcessTransparent
= false;
545 mbContainsTransparent
= false;
550 void ZBufferProcessor3D::processTransparent(const primitive3d::Primitive3DSequence
& rSource
)
552 if(mpBZPixelRaster
&& mbContainsTransparent
)
554 mbProcessTransparent
= true;
559 void ZBufferProcessor3D::rasterconvertB3DPolygon(const attribute::MaterialAttribute3D
& rMaterial
, const basegfx::B3DPolygon
& rHairline
) const
563 mpZBufferRasterConverter3D
->setCurrentMaterial(rMaterial
);
565 if(mnAntiAlialize
> 1)
567 const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
571 basegfx::B3DHomMatrix aTransform
;
572 basegfx::B3DPolygon
aSnappedHairline(rHairline
);
573 const double fScaleDown(1.0 / mnAntiAlialize
);
574 const double fScaleUp(mnAntiAlialize
);
576 // take oversampling out
577 aTransform
.scale(fScaleDown
, fScaleDown
, 1.0);
578 aSnappedHairline
.transform(aTransform
);
581 aSnappedHairline
= basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aSnappedHairline
);
583 // add oversampling again
584 aTransform
.identity();
585 aTransform
.scale(fScaleUp
, fScaleUp
, 1.0);
589 // when really want to go to single pixel lines, move to center.
590 // Without this translation, all hor/ver hairlines will be centered exactly
591 // between two pixel lines (which looks best)
592 const double fTranslateToCenter(mnAntiAlialize
* 0.5);
593 aTransform
.translate(fTranslateToCenter
, fTranslateToCenter
, 0.0);
596 aSnappedHairline
.transform(aTransform
);
598 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(aSnappedHairline
, 0, mpBZPixelRaster
->getHeight(), mnAntiAlialize
);
602 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(rHairline
, 0, mpBZPixelRaster
->getHeight(), mnAntiAlialize
);
607 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(rHairline
, 0, mpBZPixelRaster
->getHeight(), 1);
612 void ZBufferProcessor3D::rasterconvertB3DPolyPolygon(const attribute::MaterialAttribute3D
& rMaterial
, const basegfx::B3DPolyPolygon
& rFill
) const
616 mpZBufferRasterConverter3D
->setCurrentMaterial(rMaterial
);
617 mpZBufferRasterConverter3D
->rasterconvertB3DPolyPolygon(rFill
, &maInvEyeToView
, 0, mpBZPixelRaster
->getHeight());
621 ZBufferProcessor3D::ZBufferProcessor3D(
622 const geometry::ViewInformation3D
& rViewInformation3D
,
623 const geometry::ViewInformation2D
& rViewInformation2D
,
624 const attribute::SdrSceneAttribute
& rSdrSceneAttribute
,
625 const attribute::SdrLightingAttribute
& rSdrLightingAttribute
,
628 const basegfx::B2DRange
& rVisiblePart
,
629 sal_uInt16 nAntiAlialize
)
630 : DefaultProcessor3D(rViewInformation3D
, rSdrSceneAttribute
, rSdrLightingAttribute
),
633 mpZBufferRasterConverter3D(0),
634 mnAntiAlialize(nAntiAlialize
),
635 mbProcessTransparent(false),
636 mbContainsTransparent(false)
638 // generate ViewSizes
639 const double fFullViewSizeX((rViewInformation2D
.getObjectToViewTransformation() * basegfx::B2DVector(fSizeX
, 0.0)).getLength());
640 const double fFullViewSizeY((rViewInformation2D
.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fSizeY
)).getLength());
641 const double fViewSizeX(fFullViewSizeX
* rVisiblePart
.getWidth());
642 const double fViewSizeY(fFullViewSizeY
* rVisiblePart
.getHeight());
644 // generate RasterWidth and RasterHeight
645 const sal_uInt32
nRasterWidth((sal_uInt32
)basegfx::fround(fViewSizeX
) + 1);
646 const sal_uInt32
nRasterHeight((sal_uInt32
)basegfx::fround(fViewSizeY
) + 1);
648 if(nRasterWidth
&& nRasterHeight
)
650 // create view unit buffer
651 mpBZPixelRaster
= new basegfx::BZPixelRaster(
652 mnAntiAlialize
? nRasterWidth
* mnAntiAlialize
: nRasterWidth
,
653 mnAntiAlialize
? nRasterHeight
* mnAntiAlialize
: nRasterHeight
);
654 OSL_ENSURE(mpBZPixelRaster
, "ZBufferProcessor3D: Could not allocate basegfx::BZPixelRaster (!)");
656 // create DeviceToView for Z-Buffer renderer since Z is handled
657 // different from standard 3D transformations (Z is mirrored). Also
658 // the transformation includes the step from unit device coordinates
659 // to discrete units ([-1.0 .. 1.0] -> [minDiscrete .. maxDiscrete]
661 basegfx::B3DHomMatrix aDeviceToView
;
666 // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also
668 // - flip Y due to screen orientation
669 // - flip Z due to Z-Buffer orientation from back to front
671 aDeviceToView
.scale(0.5, -0.5, -0.5);
672 aDeviceToView
.translate(0.5, 0.5, 0.5);
678 // bring from [0.0 .. 1.0] in X,Y and Z to view cordinates
681 // also: scale Z to [1.5 .. 65534.5]. Normally, a range of [0.0 .. 65535.0]
682 // could be used, but a 'unused' value is needed, so '0' is used what reduces
683 // the range to [1.0 .. 65535.0]. It has also shown that small numerical errors
684 // (smaller as basegfx::fTools::mfSmallValue, which is 0.000000001) happen.
685 // Instead of checking those by basegfx::fTools methods which would cost
686 // runtime, just add another 0.5 tolerance to the start and end of the Z-Buffer
687 // range, thus resulting in [1.5 .. 65534.5]
688 const double fMaxZDepth(65533.0);
689 aDeviceToView
.translate(-rVisiblePart
.getMinX(), -rVisiblePart
.getMinY(), 0.0);
692 aDeviceToView
.scale(fFullViewSizeX
* mnAntiAlialize
, fFullViewSizeY
* mnAntiAlialize
, fMaxZDepth
);
694 aDeviceToView
.scale(fFullViewSizeX
, fFullViewSizeY
, fMaxZDepth
);
696 aDeviceToView
.translate(0.0, 0.0, 1.5);
699 // update local ViewInformation3D with own DeviceToView
700 const geometry::ViewInformation3D
aNewViewInformation3D(
701 getViewInformation3D().getObjectTransformation(),
702 getViewInformation3D().getOrientation(),
703 getViewInformation3D().getProjection(),
705 getViewInformation3D().getViewTime(),
706 getViewInformation3D().getExtendedInformationSequence());
707 updateViewInformation(aNewViewInformation3D
);
709 // prepare inverse EyeToView transformation. This can be done in constructor
710 // since changes in object transformations when processing TransformPrimitive3Ds
711 // do not influence this prepared partial transformation
712 maInvEyeToView
= getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
713 maInvEyeToView
.invert();
715 // prepare maRasterRange
716 maRasterRange
.reset();
717 maRasterRange
.expand(basegfx::B2DPoint(0.0, 0.0));
718 maRasterRange
.expand(basegfx::B2DPoint(mpBZPixelRaster
->getWidth(), mpBZPixelRaster
->getHeight()));
720 // create the raster converter
721 mpZBufferRasterConverter3D
= new ZBufferRasterConverter3D(*mpBZPixelRaster
, *this);
725 ZBufferProcessor3D::~ZBufferProcessor3D()
729 delete mpZBufferRasterConverter3D
;
730 delete mpBZPixelRaster
;
734 BitmapEx
ZBufferProcessor3D::getBitmapEx() const
738 return BPixelRasterToBitmapEx(*mpBZPixelRaster
, mnAntiAlialize
);
743 } // end of namespace processor3d
744 } // end of namespace drawinglayer
746 //////////////////////////////////////////////////////////////////////////////