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 <processor3d/zbufferprocessor3d.hxx>
21 #include <basegfx/raster/bzpixelraster.hxx>
22 #include <basegfx/raster/rasterconvert3d.hxx>
23 #include <drawinglayer/attribute/materialattribute3d.hxx>
24 #include <texture/texture.hxx>
25 #include <basegfx/polygon/b3dpolygon.hxx>
26 #include <basegfx/polygon/b3dpolypolygon.hxx>
27 #include <basegfx/polygon/b3dpolygontools.hxx>
28 #include <basegfx/polygon/b3dpolypolygontools.hxx>
29 #include <drawinglayer/attribute/sdrlightingattribute3d.hxx>
31 using namespace com::sun::star
;
33 class ZBufferRasterConverter3D
: public basegfx::RasterConverter3D
36 const drawinglayer::processor3d::DefaultProcessor3D
& mrProcessor
;
37 basegfx::BZPixelRaster
& mrBuffer
;
39 // interpolators for a single line span
40 basegfx::ip_single maIntZ
;
41 basegfx::ip_triple maIntColor
;
42 basegfx::ip_triple maIntNormal
;
43 basegfx::ip_double maIntTexture
;
44 basegfx::ip_triple maIntInvTexture
;
46 // current material to use for rasterconversion
47 const drawinglayer::attribute::MaterialAttribute3D
* mpCurrentMaterial
;
49 // some boolean flags for line span interpolator usages
50 bool mbModifyColor
: 1;
52 bool mbHasTexCoor
: 1;
53 bool mbHasInvTexCoor
: 1;
57 void getTextureCoor(basegfx::B2DPoint
& rTarget
) const
61 rTarget
.setX(maIntTexture
.getX().getVal());
62 rTarget
.setY(maIntTexture
.getY().getVal());
64 else if(mbHasInvTexCoor
)
66 const double fZFactor(maIntInvTexture
.getZ().getVal());
67 const double fInvZFactor(basegfx::fTools::equalZero(fZFactor
) ? 1.0 : 1.0 / fZFactor
);
68 rTarget
.setX(maIntInvTexture
.getX().getVal() * fInvZFactor
);
69 rTarget
.setY(maIntInvTexture
.getY().getVal() * fInvZFactor
);
73 void incrementLineSpanInterpolators(double fStep
)
75 maIntZ
.increment(fStep
);
81 maIntTexture
.increment(fStep
);
83 else if(mbHasInvTexCoor
)
85 maIntInvTexture
.increment(fStep
);
91 maIntNormal
.increment(fStep
);
96 maIntColor
.increment(fStep
);
100 double decideColorAndOpacity(basegfx::BColor
& rColor
) const
102 // init values with full opacity and material color
103 OSL_ENSURE(nullptr != mpCurrentMaterial
, "CurrentMaterial not set (!)");
104 double fOpacity(1.0);
105 rColor
= mpCurrentMaterial
->getColor();
109 basegfx::B2DPoint
aTexCoor(0.0, 0.0);
110 getTextureCoor(aTexCoor
);
112 if(mrProcessor
.getGeoTexSvx())
114 // calc color in spot. This may also set to invisible already when
115 // e.g. bitmap textures have transparent parts
116 mrProcessor
.getGeoTexSvx()->modifyBColor(aTexCoor
, rColor
, fOpacity
);
119 if(basegfx::fTools::more(fOpacity
, 0.0) && mrProcessor
.getTransparenceGeoTexSvx())
121 // calc opacity. Object has a 2nd texture, a transparence texture
122 mrProcessor
.getTransparenceGeoTexSvx()->modifyOpacity(aTexCoor
, fOpacity
);
126 if(basegfx::fTools::more(fOpacity
, 0.0))
128 if(mrProcessor
.getGeoTexSvx())
132 // blend texture with phong
133 rColor
= mrProcessor
.getSdrLightingAttribute().solveColorModel(
134 basegfx::B3DVector(maIntNormal
.getX().getVal(), maIntNormal
.getY().getVal(), maIntNormal
.getZ().getVal()),
136 mpCurrentMaterial
->getSpecular(),
137 mpCurrentMaterial
->getEmission(),
138 mpCurrentMaterial
->getSpecularIntensity());
142 // blend texture with gouraud
143 basegfx::BColor
aBlendColor(maIntColor
.getX().getVal(), maIntColor
.getY().getVal(), maIntColor
.getZ().getVal());
144 rColor
*= aBlendColor
;
146 else if(mrProcessor
.getModulate())
148 // blend texture with single material color
149 rColor
*= mpCurrentMaterial
->getColor();
156 // modify color with phong
157 rColor
= mrProcessor
.getSdrLightingAttribute().solveColorModel(
158 basegfx::B3DVector(maIntNormal
.getX().getVal(), maIntNormal
.getY().getVal(), maIntNormal
.getZ().getVal()),
160 mpCurrentMaterial
->getSpecular(),
161 mpCurrentMaterial
->getEmission(),
162 mpCurrentMaterial
->getSpecularIntensity());
166 // modify color with gouraud
167 rColor
.setRed(maIntColor
.getX().getVal());
168 rColor
.setGreen(maIntColor
.getY().getVal());
169 rColor
.setBlue(maIntColor
.getZ().getVal());
175 rColor
= mrProcessor
.getBColorModifierStack().getModifiedColor(rColor
);
182 void setupLineSpanInterpolators(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
)
184 // get inverse XDelta
185 const double xInvDelta(1.0 / (rB
.getX().getVal() - rA
.getX().getVal()));
187 // prepare Z-interpolator
188 const double fZA(rA
.getZ().getVal());
189 const double fZB(rB
.getZ().getVal());
190 maIntZ
= basegfx::ip_single(fZA
, (fZB
- fZA
) * xInvDelta
);
192 // get bools and init other interpolators on demand accordingly
193 mbModifyColor
= mrProcessor
.getBColorModifierStack().count();
194 mbHasTexCoor
= SCANLINE_EMPTY_INDEX
!= rA
.getTextureIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getTextureIndex();
195 mbHasInvTexCoor
= SCANLINE_EMPTY_INDEX
!= rA
.getInverseTextureIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getInverseTextureIndex();
196 const bool bTextureActive(mrProcessor
.getGeoTexSvx() || mrProcessor
.getTransparenceGeoTexSvx());
197 mbUseTex
= bTextureActive
&& (mbHasTexCoor
|| mbHasInvTexCoor
|| mrProcessor
.getSimpleTextureActive());
198 const bool bUseColorTex(mbUseTex
&& mrProcessor
.getGeoTexSvx());
199 const bool bNeedNrmOrCol(!bUseColorTex
|| mrProcessor
.getModulate());
200 mbUseNrm
= bNeedNrmOrCol
&& SCANLINE_EMPTY_INDEX
!= rA
.getNormalIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getNormalIndex();
201 mbUseCol
= !mbUseNrm
&& bNeedNrmOrCol
&& SCANLINE_EMPTY_INDEX
!= rA
.getColorIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getColorIndex();
207 const basegfx::ip_double
& rTA(getTextureInterpolators()[rA
.getTextureIndex()]);
208 const basegfx::ip_double
& rTB(getTextureInterpolators()[rB
.getTextureIndex()]);
209 maIntTexture
= basegfx::ip_double(
210 rTA
.getX().getVal(), (rTB
.getX().getVal() - rTA
.getX().getVal()) * xInvDelta
,
211 rTA
.getY().getVal(), (rTB
.getY().getVal() - rTA
.getY().getVal()) * xInvDelta
);
213 else if(mbHasInvTexCoor
)
215 const basegfx::ip_triple
& rITA(getInverseTextureInterpolators()[rA
.getInverseTextureIndex()]);
216 const basegfx::ip_triple
& rITB(getInverseTextureInterpolators()[rB
.getInverseTextureIndex()]);
217 maIntInvTexture
= basegfx::ip_triple(
218 rITA
.getX().getVal(), (rITB
.getX().getVal() - rITA
.getX().getVal()) * xInvDelta
,
219 rITA
.getY().getVal(), (rITB
.getY().getVal() - rITA
.getY().getVal()) * xInvDelta
,
220 rITA
.getZ().getVal(), (rITB
.getZ().getVal() - rITA
.getZ().getVal()) * xInvDelta
);
226 const basegfx::ip_triple
& rNA(getNormalInterpolators()[rA
.getNormalIndex()]);
227 const basegfx::ip_triple
& rNB(getNormalInterpolators()[rB
.getNormalIndex()]);
228 maIntNormal
= basegfx::ip_triple(
229 rNA
.getX().getVal(), (rNB
.getX().getVal() - rNA
.getX().getVal()) * xInvDelta
,
230 rNA
.getY().getVal(), (rNB
.getY().getVal() - rNA
.getY().getVal()) * xInvDelta
,
231 rNA
.getZ().getVal(), (rNB
.getZ().getVal() - rNA
.getZ().getVal()) * xInvDelta
);
236 const basegfx::ip_triple
& rCA(getColorInterpolators()[rA
.getColorIndex()]);
237 const basegfx::ip_triple
& rCB(getColorInterpolators()[rB
.getColorIndex()]);
238 maIntColor
= basegfx::ip_triple(
239 rCA
.getX().getVal(), (rCB
.getX().getVal() - rCA
.getX().getVal()) * xInvDelta
,
240 rCA
.getY().getVal(), (rCB
.getY().getVal() - rCA
.getY().getVal()) * xInvDelta
,
241 rCA
.getZ().getVal(), (rCB
.getZ().getVal() - rCA
.getZ().getVal()) * xInvDelta
);
245 virtual void processLineSpan(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
, sal_Int32 nLine
, sal_uInt32 nSpanCount
) override
;
248 ZBufferRasterConverter3D(basegfx::BZPixelRaster
& rBuffer
, const drawinglayer::processor3d::ZBufferProcessor3D
& rProcessor
)
249 : basegfx::RasterConverter3D(),
250 mrProcessor(rProcessor
),
257 mpCurrentMaterial(nullptr),
258 mbModifyColor(false),
261 mbHasInvTexCoor(false),
266 void setCurrentMaterial(const drawinglayer::attribute::MaterialAttribute3D
& rMaterial
)
268 mpCurrentMaterial
= &rMaterial
;
272 void ZBufferRasterConverter3D::processLineSpan(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
, sal_Int32 nLine
, sal_uInt32 nSpanCount
)
274 if(nSpanCount
& 0x0001)
277 if(nLine
< 0 || nLine
>= static_cast<sal_Int32
>(mrBuffer
.getHeight()))
280 sal_uInt32
nXA(std::min(mrBuffer
.getWidth(), static_cast<sal_uInt32
>(std::max(sal_Int32(0), basegfx::fround(rA
.getX().getVal())))));
281 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::clamp(maIntZ
.getVal(), 0.0, 65535.0));
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);
357 // helper class to buffer output for transparent rasterprimitives (filled areas
358 // and lines) until the end of processing. To ensure correct transparent
359 // visualisation, ZBuffers require to not set Z and to mix with the transparent
360 // color. If transparent rasterprimitives overlap, it gets necessary to
361 // paint transparent rasterprimitives from back to front to ensure that the
362 // mixing happens from back to front. For that purpose, transparent
363 // rasterprimitives are held in this class during the processing run, remember
364 // all data and will be rendered
366 class RasterPrimitive3D
369 std::shared_ptr
< drawinglayer::texture::GeoTexSvx
> mpGeoTexSvx
;
370 std::shared_ptr
< drawinglayer::texture::GeoTexSvx
> mpTransparenceGeoTexSvx
;
371 drawinglayer::attribute::MaterialAttribute3D maMaterial
;
372 basegfx::B3DPolyPolygon maPolyPolygon
;
377 bool mbSimpleTextureActive
: 1;
382 const std::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& pGeoTexSvx
,
383 const std::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& pTransparenceGeoTexSvx
,
384 const drawinglayer::attribute::MaterialAttribute3D
& rMaterial
,
385 const basegfx::B3DPolyPolygon
& rPolyPolygon
,
388 bool bSimpleTextureActive
,
390 : mpGeoTexSvx(pGeoTexSvx
),
391 mpTransparenceGeoTexSvx(pTransparenceGeoTexSvx
),
392 maMaterial(rMaterial
),
393 maPolyPolygon(rPolyPolygon
),
394 mfCenterZ(basegfx::utils::getRange(rPolyPolygon
).getCenter().getZ()),
395 mbModulate(bModulate
),
397 mbSimpleTextureActive(bSimpleTextureActive
),
402 bool operator<(const RasterPrimitive3D
& rComp
) const
404 return mfCenterZ
< rComp
.mfCenterZ
;
407 const std::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& getGeoTexSvx() const { return mpGeoTexSvx
; }
408 const std::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& getTransparenceGeoTexSvx() const { return mpTransparenceGeoTexSvx
; }
409 const drawinglayer::attribute::MaterialAttribute3D
& getMaterial() const { return maMaterial
; }
410 const basegfx::B3DPolyPolygon
& getPolyPolygon() const { return maPolyPolygon
; }
411 bool getModulate() const { return mbModulate
; }
412 bool getFilter() const { return mbFilter
; }
413 bool getSimpleTextureActive() const { return mbSimpleTextureActive
; }
414 bool getIsLine() const { return mbIsLine
; }
417 namespace drawinglayer::processor3d
419 void ZBufferProcessor3D::rasterconvertB3DPolygon(const attribute::MaterialAttribute3D
& rMaterial
, const basegfx::B3DPolygon
& rHairline
) const
421 if(getTransparenceCounter())
423 // transparent output; record for later sorting and painting from
425 if(!mpRasterPrimitive3Ds
)
427 const_cast< ZBufferProcessor3D
* >(this)->mpRasterPrimitive3Ds
.reset( new std::vector
< RasterPrimitive3D
> );
430 mpRasterPrimitive3Ds
->push_back(RasterPrimitive3D(
432 getTransparenceGeoTexSvx(),
434 basegfx::B3DPolyPolygon(rHairline
),
437 getSimpleTextureActive(),
442 // do rasterconversion
443 mpZBufferRasterConverter3D
->setCurrentMaterial(rMaterial
);
445 if(mnAntiAlialize
> 1)
447 const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
451 basegfx::B3DHomMatrix aTransform
;
452 basegfx::B3DPolygon
aSnappedHairline(rHairline
);
453 const double fScaleDown(1.0 / mnAntiAlialize
);
454 const double fScaleUp(mnAntiAlialize
);
456 // take oversampling out
457 aTransform
.scale(fScaleDown
, fScaleDown
, 1.0);
458 aSnappedHairline
.transform(aTransform
);
461 aSnappedHairline
= basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aSnappedHairline
);
463 // add oversampling again
464 aTransform
.identity();
465 aTransform
.scale(fScaleUp
, fScaleUp
, 1.0);
467 aSnappedHairline
.transform(aTransform
);
469 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(aSnappedHairline
, mnStartLine
, mnStopLine
, mnAntiAlialize
);
473 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(rHairline
, mnStartLine
, mnStopLine
, mnAntiAlialize
);
478 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(rHairline
, mnStartLine
, mnStopLine
, 1);
483 void ZBufferProcessor3D::rasterconvertB3DPolyPolygon(const attribute::MaterialAttribute3D
& rMaterial
, const basegfx::B3DPolyPolygon
& rFill
) const
485 if(getTransparenceCounter())
487 // transparent output; record for later sorting and painting from
489 if(!mpRasterPrimitive3Ds
)
491 const_cast< ZBufferProcessor3D
* >(this)->mpRasterPrimitive3Ds
.reset( new std::vector
< RasterPrimitive3D
> );
494 mpRasterPrimitive3Ds
->push_back(RasterPrimitive3D(
496 getTransparenceGeoTexSvx(),
501 getSimpleTextureActive(),
506 mpZBufferRasterConverter3D
->setCurrentMaterial(rMaterial
);
507 mpZBufferRasterConverter3D
->rasterconvertB3DPolyPolygon(rFill
, &maInvEyeToView
, mnStartLine
, mnStopLine
);
511 ZBufferProcessor3D::ZBufferProcessor3D(
512 const geometry::ViewInformation3D
& rViewInformation3D
,
513 const attribute::SdrSceneAttribute
& rSdrSceneAttribute
,
514 const attribute::SdrLightingAttribute
& rSdrLightingAttribute
,
515 const basegfx::B2DRange
& rVisiblePart
,
516 sal_uInt16 nAntiAlialize
,
517 double fFullViewSizeX
,
518 double fFullViewSizeY
,
519 basegfx::BZPixelRaster
& rBZPixelRaster
,
520 sal_uInt32 nStartLine
,
521 sal_uInt32 nStopLine
)
522 : DefaultProcessor3D(rViewInformation3D
, rSdrSceneAttribute
, rSdrLightingAttribute
),
524 mnAntiAlialize(nAntiAlialize
),
525 mnStartLine(nStartLine
),
526 mnStopLine(nStopLine
)
528 // create DeviceToView for Z-Buffer renderer since Z is handled
529 // different from standard 3D transformations (Z is mirrored). Also
530 // the transformation includes the step from unit device coordinates
531 // to discrete units ([-1.0 .. 1.0] -> [minDiscrete .. maxDiscrete]
532 basegfx::B3DHomMatrix aDeviceToView
;
537 // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also
539 // - flip Y due to screen orientation
540 // - flip Z due to Z-Buffer orientation from back to front
542 aDeviceToView
.scale(0.5, -0.5, -0.5);
543 aDeviceToView
.translate(0.5, 0.5, 0.5);
549 // bring from [0.0 .. 1.0] in X,Y and Z to view coordinates
552 // also: scale Z to [1.5 .. 65534.5]. Normally, a range of [0.0 .. 65535.0]
553 // could be used, but a 'unused' value is needed, so '0' is used what reduces
554 // the range to [1.0 .. 65535.0]. It has also shown that small numerical errors
555 // (smaller as basegfx::fTools::mfSmallValue, which is 0.000000001) happen.
556 // Instead of checking those by basegfx::fTools methods which would cost
557 // runtime, just add another 0.5 tolerance to the start and end of the Z-Buffer
558 // range, thus resulting in [1.5 .. 65534.5]
559 const double fMaxZDepth(65533.0);
560 aDeviceToView
.translate(-rVisiblePart
.getMinX(), -rVisiblePart
.getMinY(), 0.0);
563 aDeviceToView
.scale(fFullViewSizeX
* mnAntiAlialize
, fFullViewSizeY
* mnAntiAlialize
, fMaxZDepth
);
565 aDeviceToView
.scale(fFullViewSizeX
, fFullViewSizeY
, fMaxZDepth
);
567 aDeviceToView
.translate(0.0, 0.0, 1.5);
570 // update local ViewInformation3D with own DeviceToView
571 const geometry::ViewInformation3D
aNewViewInformation3D(
572 getViewInformation3D().getObjectTransformation(),
573 getViewInformation3D().getOrientation(),
574 getViewInformation3D().getProjection(),
576 getViewInformation3D().getViewTime(),
577 getViewInformation3D().getExtendedInformationSequence());
578 updateViewInformation(aNewViewInformation3D
);
580 // prepare inverse EyeToView transformation. This can be done in constructor
581 // since changes in object transformations when processing TransformPrimitive3Ds
582 // do not influence this prepared partial transformation
583 maInvEyeToView
= getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
584 maInvEyeToView
.invert();
586 // prepare maRasterRange
587 maRasterRange
.reset();
588 maRasterRange
.expand(basegfx::B2DPoint(0.0, nStartLine
));
589 maRasterRange
.expand(basegfx::B2DPoint(rBZPixelRaster
.getWidth(), nStopLine
));
591 // create the raster converter
592 mpZBufferRasterConverter3D
.reset( new ZBufferRasterConverter3D(rBZPixelRaster
, *this) );
595 ZBufferProcessor3D::~ZBufferProcessor3D()
597 mpZBufferRasterConverter3D
.reset();
599 if(mpRasterPrimitive3Ds
)
601 OSL_FAIL("ZBufferProcessor3D: destructed, but there are unrendered transparent geometries. Use ZBufferProcessor3D::finish() to render these (!)");
603 mpRasterPrimitive3Ds
.reset();
606 void ZBufferProcessor3D::finish()
608 if(!mpRasterPrimitive3Ds
)
611 // there are transparent rasterprimitives
612 const sal_uInt32
nSize(mpRasterPrimitive3Ds
->size());
616 // sort them from back to front
617 std::sort(mpRasterPrimitive3Ds
->begin(), mpRasterPrimitive3Ds
->end());
620 for(sal_uInt32
a(0); a
< nSize
; a
++)
622 // paint each one by setting the remembered data and calling
624 const RasterPrimitive3D
& rCandidate
= (*mpRasterPrimitive3Ds
)[a
];
626 mpGeoTexSvx
= rCandidate
.getGeoTexSvx();
627 mpTransparenceGeoTexSvx
= rCandidate
.getTransparenceGeoTexSvx();
628 mbModulate
= rCandidate
.getModulate();
629 mbFilter
= rCandidate
.getFilter();
630 mbSimpleTextureActive
= rCandidate
.getSimpleTextureActive();
632 if(rCandidate
.getIsLine())
634 rasterconvertB3DPolygon(
635 rCandidate
.getMaterial(),
636 rCandidate
.getPolyPolygon().getB3DPolygon(0));
640 rasterconvertB3DPolyPolygon(
641 rCandidate
.getMaterial(),
642 rCandidate
.getPolyPolygon());
646 // delete them to signal the destructor that all is done and
647 // to allow asserting there
648 mpRasterPrimitive3Ds
.reset();
651 } // end of namespace
653 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */