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/bpixelraster.hxx>
22 #include <vcl/bmpacc.hxx>
23 #include <basegfx/raster/rasterconvert3d.hxx>
24 #include <basegfx/raster/bzpixelraster.hxx>
25 #include <drawinglayer/attribute/materialattribute3d.hxx>
26 #include <drawinglayer/texture/texture.hxx>
27 #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
28 #include <drawinglayer/primitive3d/textureprimitive3d.hxx>
29 #include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
30 #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
31 #include <drawinglayer/geometry/viewinformation2d.hxx>
32 #include <basegfx/polygon/b3dpolygontools.hxx>
33 #include <basegfx/polygon/b3dpolypolygontools.hxx>
34 #include <drawinglayer/attribute/sdrlightingattribute3d.hxx>
36 using namespace com::sun::star
;
40 BitmapEx
BPixelRasterToBitmapEx(const basegfx::BPixelRaster
& rRaster
, sal_uInt16 mnAntiAlialize
)
43 const sal_uInt32
nWidth(mnAntiAlialize
? rRaster
.getWidth()/mnAntiAlialize
: rRaster
.getWidth());
44 const sal_uInt32
nHeight(mnAntiAlialize
? rRaster
.getHeight()/mnAntiAlialize
: rRaster
.getHeight());
48 const Size
aDestSize(nWidth
, nHeight
);
49 sal_uInt8
nInitAlpha(255);
50 Bitmap
aContent(aDestSize
, 24);
51 AlphaMask
aAlpha(aDestSize
, &nInitAlpha
);
52 BitmapWriteAccess
* pContent
= aContent
.AcquireWriteAccess();
53 BitmapWriteAccess
* pAlpha
= aAlpha
.AcquireWriteAccess();
55 if (pContent
&& pAlpha
)
59 const sal_uInt16
nDivisor(mnAntiAlialize
* mnAntiAlialize
);
61 for(sal_uInt32
y(0L); y
< nHeight
; y
++)
63 for(sal_uInt32
x(0L); x
< nWidth
; x
++)
68 sal_uInt16
nOpacity(0);
69 sal_uInt32
nIndex(rRaster
.getIndexFromXY(x
* mnAntiAlialize
, y
* mnAntiAlialize
));
71 for(sal_uInt32
c(0); c
< mnAntiAlialize
; c
++)
73 for(sal_uInt32
d(0); d
< mnAntiAlialize
; d
++)
75 const basegfx::BPixel
& rPixel(rRaster
.getBPixel(nIndex
++));
76 nRed
= nRed
+ rPixel
.getRed();
77 nGreen
= nGreen
+ rPixel
.getGreen();
78 nBlue
= nBlue
+ rPixel
.getBlue();
79 nOpacity
= nOpacity
+ rPixel
.getOpacity();
82 nIndex
+= rRaster
.getWidth() - mnAntiAlialize
;
85 nOpacity
= nOpacity
/ nDivisor
;
89 pContent
->SetPixel(y
, x
, BitmapColor(
90 (sal_uInt8
)(nRed
/ nDivisor
),
91 (sal_uInt8
)(nGreen
/ nDivisor
),
92 (sal_uInt8
)(nBlue
/ nDivisor
)));
93 pAlpha
->SetPixel(y
, x
, BitmapColor(255 - (sal_uInt8
)nOpacity
));
100 sal_uInt32
nIndex(0L);
102 for(sal_uInt32
y(0L); y
< nHeight
; y
++)
104 for(sal_uInt32
x(0L); x
< nWidth
; x
++)
106 const basegfx::BPixel
& rPixel(rRaster
.getBPixel(nIndex
++));
108 if(rPixel
.getOpacity())
110 pContent
->SetPixel(y
, x
, BitmapColor(rPixel
.getRed(), rPixel
.getGreen(), rPixel
.getBlue()));
111 pAlpha
->SetPixel(y
, x
, BitmapColor(255 - rPixel
.getOpacity()));
118 aAlpha
.ReleaseAccess(pAlpha
);
119 Bitmap::ReleaseAccess(pContent
);
121 aRetval
= BitmapEx(aContent
, aAlpha
);
123 // #i101811# set PrefMapMode and PrefSize at newly created Bitmap
124 aRetval
.SetPrefMapMode(MAP_PIXEL
);
125 aRetval
.SetPrefSize(Size(nWidth
, nHeight
));
130 } // end of anonymous namespace
132 class ZBufferRasterConverter3D
: public basegfx::RasterConverter3D
135 const drawinglayer::processor3d::DefaultProcessor3D
& mrProcessor
;
136 basegfx::BZPixelRaster
& mrBuffer
;
138 // interpolators for a single line span
139 basegfx::ip_single maIntZ
;
140 basegfx::ip_triple maIntColor
;
141 basegfx::ip_triple maIntNormal
;
142 basegfx::ip_double maIntTexture
;
143 basegfx::ip_triple maIntInvTexture
;
145 // current material to use for ratsreconversion
146 const drawinglayer::attribute::MaterialAttribute3D
* mpCurrentMaterial
;
149 // some boolean flags for line span interpolator usages
150 bool mbModifyColor
: 1;
152 bool mbHasTexCoor
: 1;
153 bool mbHasInvTexCoor
: 1;
157 void getTextureCoor(basegfx::B2DPoint
& rTarget
) const
161 rTarget
.setX(maIntTexture
.getX().getVal());
162 rTarget
.setY(maIntTexture
.getY().getVal());
164 else if(mbHasInvTexCoor
)
166 const double fZFactor(maIntInvTexture
.getZ().getVal());
167 const double fInvZFactor(basegfx::fTools::equalZero(fZFactor
) ? 1.0 : 1.0 / fZFactor
);
168 rTarget
.setX(maIntInvTexture
.getX().getVal() * fInvZFactor
);
169 rTarget
.setY(maIntInvTexture
.getY().getVal() * fInvZFactor
);
173 void incrementLineSpanInterpolators(double fStep
)
175 maIntZ
.increment(fStep
);
181 maIntTexture
.increment(fStep
);
183 else if(mbHasInvTexCoor
)
185 maIntInvTexture
.increment(fStep
);
191 maIntNormal
.increment(fStep
);
196 maIntColor
.increment(fStep
);
200 double decideColorAndOpacity(basegfx::BColor
& rColor
)
202 // init values with full opacity and material color
203 OSL_ENSURE(0 != mpCurrentMaterial
, "CurrentMaterial not set (!)");
204 double fOpacity(1.0);
205 rColor
= mpCurrentMaterial
->getColor();
209 basegfx::B2DPoint
aTexCoor(0.0, 0.0);
210 getTextureCoor(aTexCoor
);
212 if(mrProcessor
.getGeoTexSvx().get())
214 // calc color in spot. This may also set to invisible already when
215 // e.g. bitmap textures have transparent parts
216 mrProcessor
.getGeoTexSvx()->modifyBColor(aTexCoor
, rColor
, fOpacity
);
219 if(basegfx::fTools::more(fOpacity
, 0.0) && mrProcessor
.getTransparenceGeoTexSvx().get())
221 // calc opacity. Object has a 2nd texture, a transparence texture
222 mrProcessor
.getTransparenceGeoTexSvx()->modifyOpacity(aTexCoor
, fOpacity
);
226 if(basegfx::fTools::more(fOpacity
, 0.0))
228 if(mrProcessor
.getGeoTexSvx().get())
232 // blend texture with phong
233 rColor
= mrProcessor
.getSdrLightingAttribute().solveColorModel(
234 basegfx::B3DVector(maIntNormal
.getX().getVal(), maIntNormal
.getY().getVal(), maIntNormal
.getZ().getVal()),
236 mpCurrentMaterial
->getSpecular(),
237 mpCurrentMaterial
->getEmission(),
238 mpCurrentMaterial
->getSpecularIntensity());
242 // blend texture with gouraud
243 basegfx::BColor
aBlendColor(maIntColor
.getX().getVal(), maIntColor
.getY().getVal(), maIntColor
.getZ().getVal());
244 rColor
*= aBlendColor
;
246 else if(mrProcessor
.getModulate())
248 // blend texture with single material color
249 rColor
*= mpCurrentMaterial
->getColor();
256 // modify color 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 // modify color with gouraud
267 rColor
.setRed(maIntColor
.getX().getVal());
268 rColor
.setGreen(maIntColor
.getY().getVal());
269 rColor
.setBlue(maIntColor
.getZ().getVal());
275 rColor
= mrProcessor
.getBColorModifierStack().getModifiedColor(rColor
);
282 void setupLineSpanInterpolators(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
)
284 // get inverse XDelta
285 const double xInvDelta(1.0 / (rB
.getX().getVal() - rA
.getX().getVal()));
287 // prepare Z-interpolator
288 const double fZA(rA
.getZ().getVal());
289 const double fZB(rB
.getZ().getVal());
290 maIntZ
= basegfx::ip_single(fZA
, (fZB
- fZA
) * xInvDelta
);
292 // get bools and init other interpolators on demand accordingly
293 mbModifyColor
= mrProcessor
.getBColorModifierStack().count();
294 mbHasTexCoor
= SCANLINE_EMPTY_INDEX
!= rA
.getTextureIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getTextureIndex();
295 mbHasInvTexCoor
= SCANLINE_EMPTY_INDEX
!= rA
.getInverseTextureIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getInverseTextureIndex();
296 const bool bTextureActive(mrProcessor
.getGeoTexSvx().get() || mrProcessor
.getTransparenceGeoTexSvx().get());
297 mbUseTex
= bTextureActive
&& (mbHasTexCoor
|| mbHasInvTexCoor
|| mrProcessor
.getSimpleTextureActive());
298 const bool bUseColorTex(mbUseTex
&& mrProcessor
.getGeoTexSvx().get());
299 const bool bNeedNrmOrCol(!bUseColorTex
|| (bUseColorTex
&& mrProcessor
.getModulate()));
300 mbUseNrm
= bNeedNrmOrCol
&& SCANLINE_EMPTY_INDEX
!= rA
.getNormalIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getNormalIndex();
301 mbUseCol
= !mbUseNrm
&& bNeedNrmOrCol
&& SCANLINE_EMPTY_INDEX
!= rA
.getColorIndex() && SCANLINE_EMPTY_INDEX
!= rB
.getColorIndex();
307 const basegfx::ip_double
& rTA(getTextureInterpolators()[rA
.getTextureIndex()]);
308 const basegfx::ip_double
& rTB(getTextureInterpolators()[rB
.getTextureIndex()]);
309 maIntTexture
= basegfx::ip_double(
310 rTA
.getX().getVal(), (rTB
.getX().getVal() - rTA
.getX().getVal()) * xInvDelta
,
311 rTA
.getY().getVal(), (rTB
.getY().getVal() - rTA
.getY().getVal()) * xInvDelta
);
313 else if(mbHasInvTexCoor
)
315 const basegfx::ip_triple
& rITA(getInverseTextureInterpolators()[rA
.getInverseTextureIndex()]);
316 const basegfx::ip_triple
& rITB(getInverseTextureInterpolators()[rB
.getInverseTextureIndex()]);
317 maIntInvTexture
= basegfx::ip_triple(
318 rITA
.getX().getVal(), (rITB
.getX().getVal() - rITA
.getX().getVal()) * xInvDelta
,
319 rITA
.getY().getVal(), (rITB
.getY().getVal() - rITA
.getY().getVal()) * xInvDelta
,
320 rITA
.getZ().getVal(), (rITB
.getZ().getVal() - rITA
.getZ().getVal()) * xInvDelta
);
326 const basegfx::ip_triple
& rNA(getNormalInterpolators()[rA
.getNormalIndex()]);
327 const basegfx::ip_triple
& rNB(getNormalInterpolators()[rB
.getNormalIndex()]);
328 maIntNormal
= basegfx::ip_triple(
329 rNA
.getX().getVal(), (rNB
.getX().getVal() - rNA
.getX().getVal()) * xInvDelta
,
330 rNA
.getY().getVal(), (rNB
.getY().getVal() - rNA
.getY().getVal()) * xInvDelta
,
331 rNA
.getZ().getVal(), (rNB
.getZ().getVal() - rNA
.getZ().getVal()) * xInvDelta
);
336 const basegfx::ip_triple
& rCA(getColorInterpolators()[rA
.getColorIndex()]);
337 const basegfx::ip_triple
& rCB(getColorInterpolators()[rB
.getColorIndex()]);
338 maIntColor
= basegfx::ip_triple(
339 rCA
.getX().getVal(), (rCB
.getX().getVal() - rCA
.getX().getVal()) * xInvDelta
,
340 rCA
.getY().getVal(), (rCB
.getY().getVal() - rCA
.getY().getVal()) * xInvDelta
,
341 rCA
.getZ().getVal(), (rCB
.getZ().getVal() - rCA
.getZ().getVal()) * xInvDelta
);
345 virtual void processLineSpan(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
, sal_Int32 nLine
, sal_uInt32 nSpanCount
) SAL_OVERRIDE
;
348 ZBufferRasterConverter3D(basegfx::BZPixelRaster
& rBuffer
, const drawinglayer::processor3d::ZBufferProcessor3D
& rProcessor
)
349 : basegfx::RasterConverter3D(),
350 mrProcessor(rProcessor
),
357 mpCurrentMaterial(0),
358 mbModifyColor(false),
361 mbHasInvTexCoor(false),
366 void setCurrentMaterial(const drawinglayer::attribute::MaterialAttribute3D
& rMaterial
)
368 mpCurrentMaterial
= &rMaterial
;
372 void ZBufferRasterConverter3D::processLineSpan(const basegfx::RasterConversionLineEntry3D
& rA
, const basegfx::RasterConversionLineEntry3D
& rB
, sal_Int32 nLine
, sal_uInt32 nSpanCount
)
374 if(!(nSpanCount
& 0x0001))
376 if(nLine
>= 0 && nLine
< (sal_Int32
)mrBuffer
.getHeight())
378 sal_uInt32
nXA(::std::min(mrBuffer
.getWidth(), (sal_uInt32
)::std::max((sal_Int32
)0, basegfx::fround(rA
.getX().getVal()))));
379 const sal_uInt32
nXB(::std::min(mrBuffer
.getWidth(), (sal_uInt32
)::std::max((sal_Int32
)0, basegfx::fround(rB
.getX().getVal()))));
383 // prepare the span interpolators
384 setupLineSpanInterpolators(rA
, rB
);
386 // bring span interpolators to start condition by incrementing with the possible difference of
387 // clamped and non-clamped XStart. Interpolators are setup relying on double precision
388 // X-values, so that difference is the correct value to compensate for possible clampings
389 incrementLineSpanInterpolators(static_cast<double>(nXA
) - rA
.getX().getVal());
391 // prepare scanline index
392 sal_uInt32
nScanlineIndex(mrBuffer
.getIndexFromXY(nXA
, static_cast<sal_uInt32
>(nLine
)));
393 basegfx::BColor aNewColor
;
397 // early-test Z values if we need to do anything at all
398 const double fNewZ(::std::max(0.0, ::std::min((double)0xffff, maIntZ
.getVal())));
399 const sal_uInt16
nNewZ(static_cast< sal_uInt16
>(fNewZ
));
400 sal_uInt16
& rOldZ(mrBuffer
.getZ(nScanlineIndex
));
404 // detect color and opacity for this pixel
405 const sal_uInt16
nOpacity(::std::max((sal_Int16
)0, static_cast< sal_Int16
>(decideColorAndOpacity(aNewColor
) * 255.0)));
409 // avoid color overrun
412 if(nOpacity
>= 0x00ff)
414 // full opacity (not transparent), set z and color
416 mrBuffer
.getBPixel(nScanlineIndex
) = basegfx::BPixel(aNewColor
, 0xff);
420 basegfx::BPixel
& rDest
= mrBuffer
.getBPixel(nScanlineIndex
);
422 if(rDest
.getOpacity())
424 // mix new color by using
425 // color' = color * (1 - opacity) + newcolor * opacity
426 const sal_uInt16
nTransparence(0x0100 - nOpacity
);
427 rDest
.setRed((sal_uInt8
)(((rDest
.getRed() * nTransparence
) + ((sal_uInt16
)(255.0 * aNewColor
.getRed()) * nOpacity
)) >> 8));
428 rDest
.setGreen((sal_uInt8
)(((rDest
.getGreen() * nTransparence
) + ((sal_uInt16
)(255.0 * aNewColor
.getGreen()) * nOpacity
)) >> 8));
429 rDest
.setBlue((sal_uInt8
)(((rDest
.getBlue() * nTransparence
) + ((sal_uInt16
)(255.0 * aNewColor
.getBlue()) * nOpacity
)) >> 8));
431 if(0xff != rDest
.getOpacity())
433 // both are transparent, mix new opacity by using
434 // opacity = newopacity * (1 - oldopacity) + oldopacity
435 rDest
.setOpacity(((sal_uInt8
)((nOpacity
* (0x0100 - rDest
.getOpacity())) >> 8)) + rDest
.getOpacity());
440 // dest is unused, set color
441 rDest
= basegfx::BPixel(aNewColor
, (sal_uInt8
)nOpacity
);
450 incrementLineSpanInterpolators(1.0);
457 // helper class to buffer output for transparent rasterprimitives (filled areas
458 // and lines) until the end of processing. To ensure correct transparent
459 // visualisation, ZBuffers require to not set Z and to mix with the transparent
460 // color. If transparent rasterprimitives overlap, it gets necessary to
461 // paint transparent rasterprimitives from back to front to ensure that the
462 // mixing happens from back to front. For that purpose, transparent
463 // rasterprimitives are held in this class during the processing run, remember
464 // all data and will be rendered
466 class RasterPrimitive3D
469 boost::shared_ptr
< drawinglayer::texture::GeoTexSvx
> mpGeoTexSvx
;
470 boost::shared_ptr
< drawinglayer::texture::GeoTexSvx
> mpTransparenceGeoTexSvx
;
471 drawinglayer::attribute::MaterialAttribute3D maMaterial
;
472 basegfx::B3DPolyPolygon maPolyPolygon
;
478 bool mbSimpleTextureActive
: 1;
483 const boost::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& pGeoTexSvx
,
484 const boost::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& pTransparenceGeoTexSvx
,
485 const drawinglayer::attribute::MaterialAttribute3D
& rMaterial
,
486 const basegfx::B3DPolyPolygon
& rPolyPolygon
,
489 bool bSimpleTextureActive
,
491 : mpGeoTexSvx(pGeoTexSvx
),
492 mpTransparenceGeoTexSvx(pTransparenceGeoTexSvx
),
493 maMaterial(rMaterial
),
494 maPolyPolygon(rPolyPolygon
),
495 mfCenterZ(basegfx::tools::getRange(rPolyPolygon
).getCenter().getZ()),
496 mbModulate(bModulate
),
498 mbSimpleTextureActive(bSimpleTextureActive
),
503 RasterPrimitive3D
& operator=(const RasterPrimitive3D
& rComp
)
505 mpGeoTexSvx
= rComp
.mpGeoTexSvx
;
506 mpTransparenceGeoTexSvx
= rComp
.mpTransparenceGeoTexSvx
;
507 maMaterial
= rComp
.maMaterial
;
508 maPolyPolygon
= rComp
.maPolyPolygon
;
509 mfCenterZ
= rComp
.mfCenterZ
;
510 mbModulate
= rComp
.mbModulate
;
511 mbFilter
= rComp
.mbFilter
;
512 mbSimpleTextureActive
= rComp
.mbSimpleTextureActive
;
513 mbIsLine
= rComp
.mbIsLine
;
518 bool operator<(const RasterPrimitive3D
& rComp
) const
520 return mfCenterZ
< rComp
.mfCenterZ
;
523 const boost::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& getGeoTexSvx() const { return mpGeoTexSvx
; }
524 const boost::shared_ptr
< drawinglayer::texture::GeoTexSvx
>& getTransparenceGeoTexSvx() const { return mpTransparenceGeoTexSvx
; }
525 const drawinglayer::attribute::MaterialAttribute3D
& getMaterial() const { return maMaterial
; }
526 const basegfx::B3DPolyPolygon
& getPolyPolygon() const { return maPolyPolygon
; }
527 bool getModulate() const { return mbModulate
; }
528 bool getFilter() const { return mbFilter
; }
529 bool getSimpleTextureActive() const { return mbSimpleTextureActive
; }
530 bool getIsLine() const { return mbIsLine
; }
533 namespace drawinglayer
535 namespace processor3d
537 void ZBufferProcessor3D::rasterconvertB3DPolygon(const attribute::MaterialAttribute3D
& rMaterial
, const basegfx::B3DPolygon
& rHairline
) const
541 if(getTransparenceCounter())
543 // transparent output; record for later sorting and painting from
545 if(!mpRasterPrimitive3Ds
)
547 const_cast< ZBufferProcessor3D
* >(this)->mpRasterPrimitive3Ds
= new std::vector
< RasterPrimitive3D
>;
550 mpRasterPrimitive3Ds
->push_back(RasterPrimitive3D(
552 getTransparenceGeoTexSvx(),
554 basegfx::B3DPolyPolygon(rHairline
),
557 getSimpleTextureActive(),
562 // do rasterconversion
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);
587 aSnappedHairline
.transform(aTransform
);
589 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(aSnappedHairline
, 0, mpBZPixelRaster
->getHeight(), mnAntiAlialize
);
593 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(rHairline
, 0, mpBZPixelRaster
->getHeight(), mnAntiAlialize
);
598 mpZBufferRasterConverter3D
->rasterconvertB3DPolygon(rHairline
, 0, mpBZPixelRaster
->getHeight(), 1);
604 void ZBufferProcessor3D::rasterconvertB3DPolyPolygon(const attribute::MaterialAttribute3D
& rMaterial
, const basegfx::B3DPolyPolygon
& rFill
) const
608 if(getTransparenceCounter())
610 // transparent output; record for later sorting and painting from
612 if(!mpRasterPrimitive3Ds
)
614 const_cast< ZBufferProcessor3D
* >(this)->mpRasterPrimitive3Ds
= new std::vector
< RasterPrimitive3D
>;
617 mpRasterPrimitive3Ds
->push_back(RasterPrimitive3D(
619 getTransparenceGeoTexSvx(),
624 getSimpleTextureActive(),
629 mpZBufferRasterConverter3D
->setCurrentMaterial(rMaterial
);
630 mpZBufferRasterConverter3D
->rasterconvertB3DPolyPolygon(rFill
, &maInvEyeToView
, 0, mpBZPixelRaster
->getHeight());
635 ZBufferProcessor3D::ZBufferProcessor3D(
636 const geometry::ViewInformation3D
& rViewInformation3D
,
637 const geometry::ViewInformation2D
& rViewInformation2D
,
638 const attribute::SdrSceneAttribute
& rSdrSceneAttribute
,
639 const attribute::SdrLightingAttribute
& rSdrLightingAttribute
,
642 const basegfx::B2DRange
& rVisiblePart
,
643 sal_uInt16 nAntiAlialize
)
644 : DefaultProcessor3D(rViewInformation3D
, rSdrSceneAttribute
, rSdrLightingAttribute
),
647 mpZBufferRasterConverter3D(0),
648 mnAntiAlialize(nAntiAlialize
),
649 mpRasterPrimitive3Ds(0)
651 // generate ViewSizes
652 const double fFullViewSizeX((rViewInformation2D
.getObjectToViewTransformation() * basegfx::B2DVector(fSizeX
, 0.0)).getLength());
653 const double fFullViewSizeY((rViewInformation2D
.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fSizeY
)).getLength());
654 const double fViewSizeX(fFullViewSizeX
* rVisiblePart
.getWidth());
655 const double fViewSizeY(fFullViewSizeY
* rVisiblePart
.getHeight());
657 // generate RasterWidth and RasterHeight
658 const sal_uInt32
nRasterWidth((sal_uInt32
)basegfx::fround(fViewSizeX
) + 1);
659 const sal_uInt32
nRasterHeight((sal_uInt32
)basegfx::fround(fViewSizeY
) + 1);
661 if(nRasterWidth
&& nRasterHeight
)
663 // create view unit buffer
664 mpBZPixelRaster
= new basegfx::BZPixelRaster(
665 mnAntiAlialize
? nRasterWidth
* mnAntiAlialize
: nRasterWidth
,
666 mnAntiAlialize
? nRasterHeight
* mnAntiAlialize
: nRasterHeight
);
667 OSL_ENSURE(mpBZPixelRaster
, "ZBufferProcessor3D: Could not allocate basegfx::BZPixelRaster (!)");
669 // create DeviceToView for Z-Buffer renderer since Z is handled
670 // different from standard 3D transformations (Z is mirrored). Also
671 // the transformation includes the step from unit device coordinates
672 // to discrete units ([-1.0 .. 1.0] -> [minDiscrete .. maxDiscrete]
674 basegfx::B3DHomMatrix aDeviceToView
;
679 // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also
681 // - flip Y due to screen orientation
682 // - flip Z due to Z-Buffer orientation from back to front
684 aDeviceToView
.scale(0.5, -0.5, -0.5);
685 aDeviceToView
.translate(0.5, 0.5, 0.5);
691 // bring from [0.0 .. 1.0] in X,Y and Z to view cordinates
694 // also: scale Z to [1.5 .. 65534.5]. Normally, a range of [0.0 .. 65535.0]
695 // could be used, but a 'unused' value is needed, so '0' is used what reduces
696 // the range to [1.0 .. 65535.0]. It has also shown that small numerical errors
697 // (smaller as basegfx::fTools::mfSmallValue, which is 0.000000001) happen.
698 // Instead of checking those by basegfx::fTools methods which would cost
699 // runtime, just add another 0.5 tolerance to the start and end of the Z-Buffer
700 // range, thus resulting in [1.5 .. 65534.5]
701 const double fMaxZDepth(65533.0);
702 aDeviceToView
.translate(-rVisiblePart
.getMinX(), -rVisiblePart
.getMinY(), 0.0);
705 aDeviceToView
.scale(fFullViewSizeX
* mnAntiAlialize
, fFullViewSizeY
* mnAntiAlialize
, fMaxZDepth
);
707 aDeviceToView
.scale(fFullViewSizeX
, fFullViewSizeY
, fMaxZDepth
);
709 aDeviceToView
.translate(0.0, 0.0, 1.5);
712 // update local ViewInformation3D with own DeviceToView
713 const geometry::ViewInformation3D
aNewViewInformation3D(
714 getViewInformation3D().getObjectTransformation(),
715 getViewInformation3D().getOrientation(),
716 getViewInformation3D().getProjection(),
718 getViewInformation3D().getViewTime(),
719 getViewInformation3D().getExtendedInformationSequence());
720 updateViewInformation(aNewViewInformation3D
);
722 // prepare inverse EyeToView transformation. This can be done in constructor
723 // since changes in object transformations when processing TransformPrimitive3Ds
724 // do not influence this prepared partial transformation
725 maInvEyeToView
= getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
726 maInvEyeToView
.invert();
728 // prepare maRasterRange
729 maRasterRange
.reset();
730 maRasterRange
.expand(basegfx::B2DPoint(0.0, 0.0));
731 maRasterRange
.expand(basegfx::B2DPoint(mpBZPixelRaster
->getWidth(), mpBZPixelRaster
->getHeight()));
733 // create the raster converter
734 mpZBufferRasterConverter3D
= new ZBufferRasterConverter3D(*mpBZPixelRaster
, *this);
738 ZBufferProcessor3D::~ZBufferProcessor3D()
742 delete mpZBufferRasterConverter3D
;
743 delete mpBZPixelRaster
;
746 if(mpRasterPrimitive3Ds
)
748 OSL_FAIL("ZBufferProcessor3D: destructed, but there are unrendered transparent geometries. Use ZBufferProcessor3D::finish() to render these (!)");
749 delete mpRasterPrimitive3Ds
;
753 void ZBufferProcessor3D::finish()
755 if(mpRasterPrimitive3Ds
)
757 // there are transparent rasterprimitives
758 const sal_uInt32
nSize(mpRasterPrimitive3Ds
->size());
762 // sort them from back to front
763 std::sort(mpRasterPrimitive3Ds
->begin(), mpRasterPrimitive3Ds
->end());
766 for(sal_uInt32
a(0); a
< nSize
; a
++)
768 // paint each one by setting the remembered data and calling
770 const RasterPrimitive3D
& rCandidate
= (*mpRasterPrimitive3Ds
)[a
];
772 mpGeoTexSvx
= rCandidate
.getGeoTexSvx();
773 mpTransparenceGeoTexSvx
= rCandidate
.getTransparenceGeoTexSvx();
774 mbModulate
= rCandidate
.getModulate();
775 mbFilter
= rCandidate
.getFilter();
776 mbSimpleTextureActive
= rCandidate
.getSimpleTextureActive();
778 if(rCandidate
.getIsLine())
780 rasterconvertB3DPolygon(
781 rCandidate
.getMaterial(),
782 rCandidate
.getPolyPolygon().getB3DPolygon(0));
786 rasterconvertB3DPolyPolygon(
787 rCandidate
.getMaterial(),
788 rCandidate
.getPolyPolygon());
792 // delete them to signal the destructor that all is done and
793 // to allow asserting there
794 delete mpRasterPrimitive3Ds
;
795 mpRasterPrimitive3Ds
= 0;
799 BitmapEx
ZBufferProcessor3D::getBitmapEx() const
803 return BPixelRasterToBitmapEx(*mpBZPixelRaster
, mnAntiAlialize
);
808 } // end of namespace processor3d
809 } // end of namespace drawinglayer
811 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */