1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <drawinglayer/processor3d/zbufferprocessor3d.hxx>
21 #include <basegfx/raster/bzpixelraster.hxx>
22 #include <basegfx/raster/rasterconvert3d.hxx>
23 #include <drawinglayer/attribute/materialattribute3d.hxx>
24 #include <drawinglayer/texture/texture.hxx>
25 #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
26 #include <drawinglayer/primitive3d/textureprimitive3d.hxx>
27 #include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
28 #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
29 #include <drawinglayer/geometry/viewinformation2d.hxx>
30 #include <basegfx/polygon/b3dpolygontools.hxx>
31 #include <basegfx/polygon/b3dpolypolygontools.hxx>
32 #include <drawinglayer/attribute/sdrlightingattribute3d.hxx>
34 using namespace com::sun::star
;
36 class ZBufferRasterConverter3D
: public basegfx::RasterConverter3D
39 const drawinglayer::processor3d::DefaultProcessor3D
& mrProcessor
;
40 basegfx::BZPixelRaster
& mrBuffer
;
42 // interpolators for a single line span
43 basegfx::ip_single maIntZ
;
44 basegfx::ip_triple maIntColor
;
45 basegfx::ip_triple maIntNormal
;
46 basegfx::ip_double maIntTexture
;
47 basegfx::ip_triple maIntInvTexture
;
49 // current material to use for rasterconversion
50 const drawinglayer::attribute::MaterialAttribute3D
* mpCurrentMaterial
;
52 // some boolean flags for line span interpolator usages
53 bool mbModifyColor
: 1;
55 bool mbHasTexCoor
: 1;
56 bool mbHasInvTexCoor
: 1;
60 void getTextureCoor(basegfx::B2DPoint
& rTarget
) const
64 rTarget
.setX(maIntTexture
.getX().getVal());
65 rTarget
.setY(maIntTexture
.getY().getVal());
67 else if(mbHasInvTexCoor
)
69 const double fZFactor(maIntInvTexture
.getZ().getVal());
70 const double fInvZFactor(basegfx::fTools::equalZero(fZFactor
) ? 1.0 : 1.0 / fZFactor
);
71 rTarget
.setX(maIntInvTexture
.getX().getVal() * fInvZFactor
);
72 rTarget
.setY(maIntInvTexture
.getY().getVal() * fInvZFactor
);
76 void incrementLineSpanInterpolators(double fStep
)
78 maIntZ
.increment(fStep
);
84 maIntTexture
.increment(fStep
);
86 else if(mbHasInvTexCoor
)
88 maIntInvTexture
.increment(fStep
);
94 maIntNormal
.increment(fStep
);
99 maIntColor
.increment(fStep
);
103 double decideColorAndOpacity(basegfx::BColor
& rColor
) const
105 // init values with full opacity and material color
106 OSL_ENSURE(nullptr != mpCurrentMaterial
, "CurrentMaterial not set (!)");
107 double fOpacity(1.0);
108 rColor
= mpCurrentMaterial
->getColor();
112 basegfx::B2DPoint
aTexCoor(0.0, 0.0);
113 getTextureCoor(aTexCoor
);
115 if(mrProcessor
.getGeoTexSvx().get())
117 // calc color in spot. This may also set to invisible already when
118 // e.g. bitmap textures have transparent parts
119 mrProcessor
.getGeoTexSvx()->modifyBColor(aTexCoor
, rColor
, fOpacity
);
122 if(basegfx::fTools::more(fOpacity
, 0.0) && mrProcessor
.getTransparenceGeoTexSvx().get())
124 // calc opacity. Object has a 2nd texture, a transparence texture
125 mrProcessor
.getTransparenceGeoTexSvx()->modifyOpacity(aTexCoor
, fOpacity
);
129 if(basegfx::fTools::more(fOpacity
, 0.0))
131 if(mrProcessor
.getGeoTexSvx().get())
135 // blend texture with phong
136 rColor
= mrProcessor
.getSdrLightingAttribute().solveColorModel(
137 basegfx::B3DVector(maIntNormal
.getX().getVal(), maIntNormal
.getY().getVal(), maIntNormal
.getZ().getVal()),
139 mpCurrentMaterial
->getSpecular(),
140 mpCurrentMaterial
->getEmission(),
141 mpCurrentMaterial
->getSpecularIntensity());
145 // blend texture with gouraud
146 basegfx::BColor
aBlendColor(maIntColor
.getX().getVal(), maIntColor
.getY().getVal(), maIntColor
.getZ().getVal());
147 rColor
*= aBlendColor
;
149 else if(mrProcessor
.getModulate())
151 // blend texture with single material color
152 rColor
*= mpCurrentMaterial
->getColor();
159 // modify color with phong
160 rColor
= mrProcessor
.getSdrLightingAttribute().solveColorModel(
161 basegfx::B3DVector(maIntNormal
.getX().getVal(), maIntNormal
.getY().getVal(), maIntNormal
.getZ().getVal()),
163 mpCurrentMaterial
->getSpecular(),
164 mpCurrentMaterial
->getEmission(),
165 mpCurrentMaterial
->getSpecularIntensity());
169 // modify color with gouraud
170 rColor
.setRed(maIntColor
.getX().getVal());
171 rColor
.setGreen(maIntColor
.getY().getVal());
172 rColor
.setBlue(maIntColor
.getZ().getVal());
178 rColor
= mrProcessor
.getBColorModifierStack().getModifiedColor(rColor
);
185 void setupLineSpanInterpolators(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
)
187 // get inverse XDelta
188 const double xInvDelta(1.0 / (rB
.getX().getVal() - rA
.getX().getVal()));
190 // prepare Z-interpolator
191 const double fZA(rA
.getZ().getVal());
192 const double fZB(rB
.getZ().getVal());
193 maIntZ
= basegfx::ip_single(fZA
, (fZB
- fZA
) * xInvDelta
);
195 // get bools and init other interpolators on demand accordingly
196 mbModifyColor
= mrProcessor
.getBColorModifierStack().count();
197 mbHasTexCoor
= SCANLINE_EMPTY_INDEX
!= rA
.getTextureIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getTextureIndex();
198 mbHasInvTexCoor
= SCANLINE_EMPTY_INDEX
!= rA
.getInverseTextureIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getInverseTextureIndex();
199 const bool bTextureActive(mrProcessor
.getGeoTexSvx().get() || mrProcessor
.getTransparenceGeoTexSvx().get());
200 mbUseTex
= bTextureActive
&& (mbHasTexCoor
|| mbHasInvTexCoor
|| mrProcessor
.getSimpleTextureActive());
201 const bool bUseColorTex(mbUseTex
&& mrProcessor
.getGeoTexSvx().get());
202 const bool bNeedNrmOrCol(!bUseColorTex
|| mrProcessor
.getModulate());
203 mbUseNrm
= bNeedNrmOrCol
&& SCANLINE_EMPTY_INDEX
!= rA
.getNormalIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getNormalIndex();
204 mbUseCol
= !mbUseNrm
&& bNeedNrmOrCol
&& SCANLINE_EMPTY_INDEX
!= rA
.getColorIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getColorIndex();
210 const basegfx::ip_double
& rTA(getTextureInterpolators()[rA
.getTextureIndex()]);
211 const basegfx::ip_double
& rTB(getTextureInterpolators()[rB
.getTextureIndex()]);
212 maIntTexture
= basegfx::ip_double(
213 rTA
.getX().getVal(), (rTB
.getX().getVal() - rTA
.getX().getVal()) * xInvDelta
,
214 rTA
.getY().getVal(), (rTB
.getY().getVal() - rTA
.getY().getVal()) * xInvDelta
);
216 else if(mbHasInvTexCoor
)
218 const basegfx::ip_triple
& rITA(getInverseTextureInterpolators()[rA
.getInverseTextureIndex()]);
219 const basegfx::ip_triple
& rITB(getInverseTextureInterpolators()[rB
.getInverseTextureIndex()]);
220 maIntInvTexture
= basegfx::ip_triple(
221 rITA
.getX().getVal(), (rITB
.getX().getVal() - rITA
.getX().getVal()) * xInvDelta
,
222 rITA
.getY().getVal(), (rITB
.getY().getVal() - rITA
.getY().getVal()) * xInvDelta
,
223 rITA
.getZ().getVal(), (rITB
.getZ().getVal() - rITA
.getZ().getVal()) * xInvDelta
);
229 const basegfx::ip_triple
& rNA(getNormalInterpolators()[rA
.getNormalIndex()]);
230 const basegfx::ip_triple
& rNB(getNormalInterpolators()[rB
.getNormalIndex()]);
231 maIntNormal
= basegfx::ip_triple(
232 rNA
.getX().getVal(), (rNB
.getX().getVal() - rNA
.getX().getVal()) * xInvDelta
,
233 rNA
.getY().getVal(), (rNB
.getY().getVal() - rNA
.getY().getVal()) * xInvDelta
,
234 rNA
.getZ().getVal(), (rNB
.getZ().getVal() - rNA
.getZ().getVal()) * xInvDelta
);
239 const basegfx::ip_triple
& rCA(getColorInterpolators()[rA
.getColorIndex()]);
240 const basegfx::ip_triple
& rCB(getColorInterpolators()[rB
.getColorIndex()]);
241 maIntColor
= basegfx::ip_triple(
242 rCA
.getX().getVal(), (rCB
.getX().getVal() - rCA
.getX().getVal()) * xInvDelta
,
243 rCA
.getY().getVal(), (rCB
.getY().getVal() - rCA
.getY().getVal()) * xInvDelta
,
244 rCA
.getZ().getVal(), (rCB
.getZ().getVal() - rCA
.getZ().getVal()) * xInvDelta
);
248 virtual void processLineSpan(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
, sal_Int32 nLine
, sal_uInt32 nSpanCount
) override
;
251 ZBufferRasterConverter3D(basegfx::BZPixelRaster
& rBuffer
, const drawinglayer::processor3d::ZBufferProcessor3D
& rProcessor
)
252 : basegfx::RasterConverter3D(),
253 mrProcessor(rProcessor
),
260 mpCurrentMaterial(nullptr),
261 mbModifyColor(false),
264 mbHasInvTexCoor(false),
269 void setCurrentMaterial(const drawinglayer::attribute::MaterialAttribute3D
& rMaterial
)
271 mpCurrentMaterial
= &rMaterial
;
275 void ZBufferRasterConverter3D::processLineSpan(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
, sal_Int32 nLine
, sal_uInt32 nSpanCount
)
277 if(!(nSpanCount
& 0x0001))
279 if(nLine
>= 0 && nLine
< static_cast<sal_Int32
>(mrBuffer
.getHeight()))
281 sal_uInt32
nXA(std::min(mrBuffer
.getWidth(), static_cast<sal_uInt32
>(std::max(sal_Int32(0), basegfx::fround(rA
.getX().getVal())))));
282 const sal_uInt32
nXB(std::min(mrBuffer
.getWidth(), static_cast<sal_uInt32
>(std::max(sal_Int32(0), basegfx::fround(rB
.getX().getVal())))));
286 // prepare the span interpolators
287 setupLineSpanInterpolators(rA
, rB
);
289 // bring span interpolators to start condition by incrementing with the possible difference of
290 // clamped and non-clamped XStart. Interpolators are setup relying on double precision
291 // X-values, so that difference is the correct value to compensate for possible clampings
292 incrementLineSpanInterpolators(static_cast<double>(nXA
) - rA
.getX().getVal());
294 // prepare scanline index
295 sal_uInt32
nScanlineIndex(mrBuffer
.getIndexFromXY(nXA
, static_cast<sal_uInt32
>(nLine
)));
296 basegfx::BColor aNewColor
;
300 // early-test Z values if we need to do anything at all
301 const double fNewZ(std::max(0.0, std::min(double(0xffff), maIntZ
.getVal())));
302 const sal_uInt16
nNewZ(static_cast< sal_uInt16
>(fNewZ
));
303 sal_uInt16
& rOldZ(mrBuffer
.getZ(nScanlineIndex
));
307 // detect color and opacity for this pixel
308 const sal_uInt16
nOpacity(std::max(sal_Int16(0), static_cast< sal_Int16
>(decideColorAndOpacity(aNewColor
) * 255.0)));
312 // avoid color overrun
315 if(nOpacity
>= 0x00ff)
317 // full opacity (not transparent), set z and color
319 mrBuffer
.getBPixel(nScanlineIndex
) = basegfx::BPixel(aNewColor
, 0xff);
323 basegfx::BPixel
& rDest
= mrBuffer
.getBPixel(nScanlineIndex
);
325 if(rDest
.getOpacity())
327 // mix new color by using
328 // color' = color * (1 - opacity) + newcolor * opacity
329 const sal_uInt16
nTransparence(0x0100 - nOpacity
);
330 rDest
.setRed(static_cast<sal_uInt8
>(((rDest
.getRed() * nTransparence
) + (static_cast<sal_uInt16
>(255.0 * aNewColor
.getRed()) * nOpacity
)) >> 8));
331 rDest
.setGreen(static_cast<sal_uInt8
>(((rDest
.getGreen() * nTransparence
) + (static_cast<sal_uInt16
>(255.0 * aNewColor
.getGreen()) * nOpacity
)) >> 8));
332 rDest
.setBlue(static_cast<sal_uInt8
>(((rDest
.getBlue() * nTransparence
) + (static_cast<sal_uInt16
>(255.0 * aNewColor
.getBlue()) * nOpacity
)) >> 8));
334 if(0xff != rDest
.getOpacity())
336 // both are transparent, mix new opacity by using
337 // opacity = newopacity * (1 - oldopacity) + oldopacity
338 rDest
.setOpacity(static_cast<sal_uInt8
>((nOpacity
* (0x0100 - rDest
.getOpacity())) >> 8) + rDest
.getOpacity());
343 // dest is unused, set color
344 rDest
= basegfx::BPixel(aNewColor
, static_cast<sal_uInt8
>(nOpacity
));
353 incrementLineSpanInterpolators(1.0);
360 // helper class to buffer output for transparent rasterprimitives (filled areas
361 // and lines) until the end of processing. To ensure correct transparent
362 // visualisation, ZBuffers require to not set Z and to mix with the transparent
363 // color. If transparent rasterprimitives overlap, it gets necessary to
364 // paint transparent rasterprimitives from back to front to ensure that the
365 // mixing happens from back to front. For that purpose, transparent
366 // rasterprimitives are held in this class during the processing run, remember
367 // all data and will be rendered
369 class RasterPrimitive3D
372 std::shared_ptr
< drawinglayer::texture::GeoTexSvx
> mpGeoTexSvx
;
373 std::shared_ptr
< drawinglayer::texture::GeoTexSvx
> mpTransparenceGeoTexSvx
;
374 drawinglayer::attribute::MaterialAttribute3D maMaterial
;
375 basegfx::B3DPolyPolygon maPolyPolygon
;
380 bool mbSimpleTextureActive
: 1;
385 const std::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& pGeoTexSvx
,
386 const std::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& pTransparenceGeoTexSvx
,
387 const drawinglayer::attribute::MaterialAttribute3D
& rMaterial
,
388 const basegfx::B3DPolyPolygon
& rPolyPolygon
,
391 bool bSimpleTextureActive
,
393 : mpGeoTexSvx(pGeoTexSvx
),
394 mpTransparenceGeoTexSvx(pTransparenceGeoTexSvx
),
395 maMaterial(rMaterial
),
396 maPolyPolygon(rPolyPolygon
),
397 mfCenterZ(basegfx::utils::getRange(rPolyPolygon
).getCenter().getZ()),
398 mbModulate(bModulate
),
400 mbSimpleTextureActive(bSimpleTextureActive
),
405 bool operator<(const RasterPrimitive3D
& rComp
) const
407 return mfCenterZ
< rComp
.mfCenterZ
;
410 const std::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& getGeoTexSvx() const { return mpGeoTexSvx
; }
411 const std::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& getTransparenceGeoTexSvx() const { return mpTransparenceGeoTexSvx
; }
412 const drawinglayer::attribute::MaterialAttribute3D
& getMaterial() const { return maMaterial
; }
413 const basegfx::B3DPolyPolygon
& getPolyPolygon() const { return maPolyPolygon
; }
414 bool getModulate() const { return mbModulate
; }
415 bool getFilter() const { return mbFilter
; }
416 bool getSimpleTextureActive() const { return mbSimpleTextureActive
; }
417 bool getIsLine() const { return mbIsLine
; }
420 namespace drawinglayer
422 namespace processor3d
424 void ZBufferProcessor3D::rasterconvertB3DPolygon(const attribute::MaterialAttribute3D
& rMaterial
, const basegfx::B3DPolygon
& rHairline
) const
426 if(getTransparenceCounter())
428 // transparent output; record for later sorting and painting from
430 if(!mpRasterPrimitive3Ds
)
432 const_cast< ZBufferProcessor3D
* >(this)->mpRasterPrimitive3Ds
.reset( new std::vector
< RasterPrimitive3D
> );
435 mpRasterPrimitive3Ds
->push_back(RasterPrimitive3D(
437 getTransparenceGeoTexSvx(),
439 basegfx::B3DPolyPolygon(rHairline
),
442 getSimpleTextureActive(),
447 // do rasterconversion
448 mpZBufferRasterConverter3D
->setCurrentMaterial(rMaterial
);
450 if(mnAntiAlialize
> 1)
452 const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
456 basegfx::B3DHomMatrix aTransform
;
457 basegfx::B3DPolygon
aSnappedHairline(rHairline
);
458 const double fScaleDown(1.0 / mnAntiAlialize
);
459 const double fScaleUp(mnAntiAlialize
);
461 // take oversampling out
462 aTransform
.scale(fScaleDown
, fScaleDown
, 1.0);
463 aSnappedHairline
.transform(aTransform
);
466 aSnappedHairline
= basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aSnappedHairline
);
468 // add oversampling again
469 aTransform
.identity();
470 aTransform
.scale(fScaleUp
, fScaleUp
, 1.0);
472 aSnappedHairline
.transform(aTransform
);
474 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(aSnappedHairline
, mnStartLine
, mnStopLine
, mnAntiAlialize
);
478 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(rHairline
, mnStartLine
, mnStopLine
, mnAntiAlialize
);
483 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(rHairline
, mnStartLine
, mnStopLine
, 1);
488 void ZBufferProcessor3D::rasterconvertB3DPolyPolygon(const attribute::MaterialAttribute3D
& rMaterial
, const basegfx::B3DPolyPolygon
& rFill
) const
490 if(getTransparenceCounter())
492 // transparent output; record for later sorting and painting from
494 if(!mpRasterPrimitive3Ds
)
496 const_cast< ZBufferProcessor3D
* >(this)->mpRasterPrimitive3Ds
.reset( new std::vector
< RasterPrimitive3D
> );
499 mpRasterPrimitive3Ds
->push_back(RasterPrimitive3D(
501 getTransparenceGeoTexSvx(),
506 getSimpleTextureActive(),
511 mpZBufferRasterConverter3D
->setCurrentMaterial(rMaterial
);
512 mpZBufferRasterConverter3D
->rasterconvertB3DPolyPolygon(rFill
, &maInvEyeToView
, mnStartLine
, mnStopLine
);
516 ZBufferProcessor3D::ZBufferProcessor3D(
517 const geometry::ViewInformation3D
& rViewInformation3D
,
518 const attribute::SdrSceneAttribute
& rSdrSceneAttribute
,
519 const attribute::SdrLightingAttribute
& rSdrLightingAttribute
,
520 const basegfx::B2DRange
& rVisiblePart
,
521 sal_uInt16 nAntiAlialize
,
522 double fFullViewSizeX
,
523 double fFullViewSizeY
,
524 basegfx::BZPixelRaster
& rBZPixelRaster
,
525 sal_uInt32 nStartLine
,
526 sal_uInt32 nStopLine
)
527 : DefaultProcessor3D(rViewInformation3D
, rSdrSceneAttribute
, rSdrLightingAttribute
),
529 mnAntiAlialize(nAntiAlialize
),
530 mnStartLine(nStartLine
),
531 mnStopLine(nStopLine
)
533 // create DeviceToView for Z-Buffer renderer since Z is handled
534 // different from standard 3D transformations (Z is mirrored). Also
535 // the transformation includes the step from unit device coordinates
536 // to discrete units ([-1.0 .. 1.0] -> [minDiscrete .. maxDiscrete]
537 basegfx::B3DHomMatrix aDeviceToView
;
542 // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also
544 // - flip Y due to screen orientation
545 // - flip Z due to Z-Buffer orientation from back to front
547 aDeviceToView
.scale(0.5, -0.5, -0.5);
548 aDeviceToView
.translate(0.5, 0.5, 0.5);
554 // bring from [0.0 .. 1.0] in X,Y and Z to view coordinates
557 // also: scale Z to [1.5 .. 65534.5]. Normally, a range of [0.0 .. 65535.0]
558 // could be used, but a 'unused' value is needed, so '0' is used what reduces
559 // the range to [1.0 .. 65535.0]. It has also shown that small numerical errors
560 // (smaller as basegfx::fTools::mfSmallValue, which is 0.000000001) happen.
561 // Instead of checking those by basegfx::fTools methods which would cost
562 // runtime, just add another 0.5 tolerance to the start and end of the Z-Buffer
563 // range, thus resulting in [1.5 .. 65534.5]
564 const double fMaxZDepth(65533.0);
565 aDeviceToView
.translate(-rVisiblePart
.getMinX(), -rVisiblePart
.getMinY(), 0.0);
568 aDeviceToView
.scale(fFullViewSizeX
* mnAntiAlialize
, fFullViewSizeY
* mnAntiAlialize
, fMaxZDepth
);
570 aDeviceToView
.scale(fFullViewSizeX
, fFullViewSizeY
, fMaxZDepth
);
572 aDeviceToView
.translate(0.0, 0.0, 1.5);
575 // update local ViewInformation3D with own DeviceToView
576 const geometry::ViewInformation3D
aNewViewInformation3D(
577 getViewInformation3D().getObjectTransformation(),
578 getViewInformation3D().getOrientation(),
579 getViewInformation3D().getProjection(),
581 getViewInformation3D().getViewTime(),
582 getViewInformation3D().getExtendedInformationSequence());
583 updateViewInformation(aNewViewInformation3D
);
585 // prepare inverse EyeToView transformation. This can be done in constructor
586 // since changes in object transformations when processing TransformPrimitive3Ds
587 // do not influence this prepared partial transformation
588 maInvEyeToView
= getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
589 maInvEyeToView
.invert();
591 // prepare maRasterRange
592 maRasterRange
.reset();
593 maRasterRange
.expand(basegfx::B2DPoint(0.0, nStartLine
));
594 maRasterRange
.expand(basegfx::B2DPoint(rBZPixelRaster
.getWidth(), nStopLine
));
596 // create the raster converter
597 mpZBufferRasterConverter3D
.reset( new ZBufferRasterConverter3D(rBZPixelRaster
, *this) );
600 ZBufferProcessor3D::~ZBufferProcessor3D()
602 mpZBufferRasterConverter3D
.reset();
604 if(mpRasterPrimitive3Ds
)
606 OSL_FAIL("ZBufferProcessor3D: destructed, but there are unrendered transparent geometries. Use ZBufferProcessor3D::finish() to render these (!)");
608 mpRasterPrimitive3Ds
.reset();
611 void ZBufferProcessor3D::finish()
613 if(mpRasterPrimitive3Ds
)
615 // there are transparent rasterprimitives
616 const sal_uInt32
nSize(mpRasterPrimitive3Ds
->size());
620 // sort them from back to front
621 std::sort(mpRasterPrimitive3Ds
->begin(), mpRasterPrimitive3Ds
->end());
624 for(sal_uInt32
a(0); a
< nSize
; a
++)
626 // paint each one by setting the remembered data and calling
628 const RasterPrimitive3D
& rCandidate
= (*mpRasterPrimitive3Ds
)[a
];
630 mpGeoTexSvx
= rCandidate
.getGeoTexSvx();
631 mpTransparenceGeoTexSvx
= rCandidate
.getTransparenceGeoTexSvx();
632 mbModulate
= rCandidate
.getModulate();
633 mbFilter
= rCandidate
.getFilter();
634 mbSimpleTextureActive
= rCandidate
.getSimpleTextureActive();
636 if(rCandidate
.getIsLine())
638 rasterconvertB3DPolygon(
639 rCandidate
.getMaterial(),
640 rCandidate
.getPolyPolygon().getB3DPolygon(0));
644 rasterconvertB3DPolyPolygon(
645 rCandidate
.getMaterial(),
646 rCandidate
.getPolyPolygon());
650 // delete them to signal the destructor that all is done and
651 // to allow asserting there
652 mpRasterPrimitive3Ds
.reset();
655 } // end of namespace processor3d
656 } // end of namespace drawinglayer
658 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */