merge the formfield patch from ooo-build
[ooovba.git] / drawinglayer / source / processor3d / zbufferprocessor3d.cxx
blob3fd02a4a4938529e9f40328859bed1d1054a46fa
1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: zbufferprocessor3d.cxx,v $
7 * $Revision: 1.5 $
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,
32 * MA 02111-1307 USA
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 //////////////////////////////////////////////////////////////////////////////
60 namespace
62 BitmapEx BPixelRasterToBitmapEx(const basegfx::BPixelRaster& rRaster, sal_uInt16 mnAntiAlialize)
64 BitmapEx aRetval;
65 const sal_uInt32 nWidth(mnAntiAlialize ? rRaster.getWidth()/mnAntiAlialize : rRaster.getWidth());
66 const sal_uInt32 nHeight(mnAntiAlialize ? rRaster.getHeight()/mnAntiAlialize : rRaster.getHeight());
68 if(nWidth && nHeight)
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)
79 if(mnAntiAlialize)
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++)
87 sal_uInt16 nRed(0);
88 sal_uInt16 nGreen(0);
89 sal_uInt16 nBlue(0);
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;
109 if(nOpacity)
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));
120 else
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()));
139 delete pContent;
140 delete pAlpha;
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));
150 return aRetval;
152 } // end of anonymous namespace
154 //////////////////////////////////////////////////////////////////////////////
156 class ZBufferRasterConverter3D : public basegfx::RasterConverter3D
158 private:
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;
172 // bitfield
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
183 if(mbHasTexCoor)
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);
201 if(mbUseTex)
203 if(mbHasTexCoor)
205 maIntTexture.increment(fStep);
207 else if(mbHasInvTexCoor)
209 maIntInvTexture.increment(fStep);
213 if(mbUseNrm)
215 maIntNormal.increment(fStep);
218 if(mbUseCol)
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();
231 if(mbUseTex)
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())
254 if(mbUseNrm)
256 // blend texture with phong
257 rColor = mrProcessor.getSdrLightingAttribute().solveColorModel(
258 basegfx::B3DVector(maIntNormal.getX().getVal(), maIntNormal.getY().getVal(), maIntNormal.getZ().getVal()),
259 rColor,
260 mpCurrentMaterial->getSpecular(),
261 mpCurrentMaterial->getEmission(),
262 mpCurrentMaterial->getSpecularIntensity());
264 else if(mbUseCol)
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();
276 else
278 if(mbUseNrm)
280 // modify color with phong
281 rColor = mrProcessor.getSdrLightingAttribute().solveColorModel(
282 basegfx::B3DVector(maIntNormal.getX().getVal(), maIntNormal.getY().getVal(), maIntNormal.getZ().getVal()),
283 rColor,
284 mpCurrentMaterial->getSpecular(),
285 mpCurrentMaterial->getEmission(),
286 mpCurrentMaterial->getSpecularIntensity());
288 else if(mbUseCol)
290 // modify color with gouraud
291 rColor.setRed(maIntColor.getX().getVal());
292 rColor.setGreen(maIntColor.getY().getVal());
293 rColor.setBlue(maIntColor.getZ().getVal());
297 if(mbModifyColor)
299 rColor = mrProcessor.getBColorModifierStack().getModifiedColor(rColor);
303 return fOpacity;
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();
327 if(mbUseTex)
329 if(mbHasTexCoor)
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);
348 if(mbUseNrm)
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);
358 if(mbUseCol)
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);
371 public:
372 ZBufferRasterConverter3D(basegfx::BZPixelRaster& rBuffer, const drawinglayer::processor3d::ZBufferProcessor3D& rProcessor)
373 : basegfx::RasterConverter3D(),
374 mrProcessor(rProcessor),
375 mrBuffer(rBuffer),
376 maIntZ(),
377 maIntColor(),
378 maIntNormal(),
379 maIntTexture(),
380 maIntInvTexture(),
381 mpCurrentMaterial(0),
382 mbModifyColor(false),
383 mbUseTex(false),
384 mbHasTexCoor(false),
385 mbUseNrm(false),
386 mbUseCol(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()))));
404 if(nXA < nXB)
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;
418 while(nXA < nXB)
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));
425 if(nNewZ > rOldZ)
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)));
430 if(nOpacity > 0)
432 // avoid color overrun
433 aNewColor.clamp();
435 if(nOpacity >= 0x00ff)
437 // full opacity, set z and color
438 rOldZ = nNewZ;
439 mrBuffer.getBPixel(nScanlineIndex) = basegfx::BPixel(aNewColor, 0xff);
441 else
443 basegfx::BPixel& rDest = mrBuffer.getBPixel(nScanlineIndex);
445 if(rDest.getOpacity())
447 // both transparent, mix color based on front pixel's opacity
448 // (the new one)
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));
461 else
463 // dest is not visible. Set color.
464 rDest = basegfx::BPixel(aNewColor, (sal_uInt8)nOpacity);
470 // increments
471 nScanlineIndex++;
472 nXA++;
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);
501 else
503 mbContainsTransparent = true;
505 break;
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);
517 break;
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);
529 break;
531 default:
533 // use the DefaultProcessor3D::processBasePrimitive3D()
534 DefaultProcessor3D::processBasePrimitive3D(rBasePrimitive);
535 break;
540 void ZBufferProcessor3D::processNonTransparent(const primitive3d::Primitive3DSequence& rSource)
542 if(mpBZPixelRaster)
544 mbProcessTransparent = false;
545 mbContainsTransparent = false;
546 process(rSource);
550 void ZBufferProcessor3D::processTransparent(const primitive3d::Primitive3DSequence& rSource)
552 if(mpBZPixelRaster && mbContainsTransparent)
554 mbProcessTransparent = true;
555 process(rSource);
559 void ZBufferProcessor3D::rasterconvertB3DPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolygon& rHairline) const
561 if(mpBZPixelRaster)
563 mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial);
565 if(mnAntiAlialize > 1)
567 const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
569 if(bForceLineSnap)
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);
580 // snap to integer
581 aSnappedHairline = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aSnappedHairline);
583 // add oversampling again
584 aTransform.identity();
585 aTransform.scale(fScaleUp, fScaleUp, 1.0);
587 if(false)
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);
600 else
602 mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize);
605 else
607 mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), 1);
612 void ZBufferProcessor3D::rasterconvertB3DPolyPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolyPolygon& rFill) const
614 if(mpBZPixelRaster)
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,
626 double fSizeX,
627 double fSizeY,
628 const basegfx::B2DRange& rVisiblePart,
629 sal_uInt16 nAntiAlialize)
630 : DefaultProcessor3D(rViewInformation3D, rSdrSceneAttribute, rSdrLightingAttribute),
631 mpBZPixelRaster(0),
632 maInvEyeToView(),
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;
664 // step one:
666 // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also
667 // necessary to
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);
676 // step two:
678 // bring from [0.0 .. 1.0] in X,Y and Z to view cordinates
680 // #i102611#
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);
691 if(mnAntiAlialize)
692 aDeviceToView.scale(fFullViewSizeX * mnAntiAlialize, fFullViewSizeY * mnAntiAlialize, fMaxZDepth);
693 else
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(),
704 aDeviceToView,
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()
727 if(mpBZPixelRaster)
729 delete mpZBufferRasterConverter3D;
730 delete mpBZPixelRaster;
734 BitmapEx ZBufferProcessor3D::getBitmapEx() const
736 if(mpBZPixelRaster)
738 return BPixelRasterToBitmapEx(*mpBZPixelRaster, mnAntiAlialize);
741 return BitmapEx();
743 } // end of namespace processor3d
744 } // end of namespace drawinglayer
746 //////////////////////////////////////////////////////////////////////////////
747 // eof