update emoji autocorrect entries from po-files
[LibreOffice.git] / drawinglayer / source / processor3d / zbufferprocessor3d.cxx
blob6ccd174df2dc5d428430e31f87d4a8e64fcea2ad
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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;
38 namespace
40 BitmapEx BPixelRasterToBitmapEx(const basegfx::BPixelRaster& rRaster, sal_uInt16 mnAntiAlialize)
42 BitmapEx aRetval;
43 const sal_uInt32 nWidth(mnAntiAlialize ? rRaster.getWidth()/mnAntiAlialize : rRaster.getWidth());
44 const sal_uInt32 nHeight(mnAntiAlialize ? rRaster.getHeight()/mnAntiAlialize : rRaster.getHeight());
46 if(nWidth && nHeight)
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)
57 if(mnAntiAlialize)
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++)
65 sal_uInt16 nRed(0);
66 sal_uInt16 nGreen(0);
67 sal_uInt16 nBlue(0);
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;
87 if(nOpacity)
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));
98 else
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));
128 return aRetval;
130 } // end of anonymous namespace
132 class ZBufferRasterConverter3D : public basegfx::RasterConverter3D
134 private:
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;
148 // bitfield
149 // some boolean flags for line span interpolator usages
150 bool mbModifyColor : 1;
151 bool mbUseTex : 1;
152 bool mbHasTexCoor : 1;
153 bool mbHasInvTexCoor : 1;
154 bool mbUseNrm : 1;
155 bool mbUseCol : 1;
157 void getTextureCoor(basegfx::B2DPoint& rTarget) const
159 if(mbHasTexCoor)
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);
177 if(mbUseTex)
179 if(mbHasTexCoor)
181 maIntTexture.increment(fStep);
183 else if(mbHasInvTexCoor)
185 maIntInvTexture.increment(fStep);
189 if(mbUseNrm)
191 maIntNormal.increment(fStep);
194 if(mbUseCol)
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();
207 if(mbUseTex)
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())
230 if(mbUseNrm)
232 // blend texture with phong
233 rColor = mrProcessor.getSdrLightingAttribute().solveColorModel(
234 basegfx::B3DVector(maIntNormal.getX().getVal(), maIntNormal.getY().getVal(), maIntNormal.getZ().getVal()),
235 rColor,
236 mpCurrentMaterial->getSpecular(),
237 mpCurrentMaterial->getEmission(),
238 mpCurrentMaterial->getSpecularIntensity());
240 else if(mbUseCol)
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();
252 else
254 if(mbUseNrm)
256 // modify color 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 // modify color with gouraud
267 rColor.setRed(maIntColor.getX().getVal());
268 rColor.setGreen(maIntColor.getY().getVal());
269 rColor.setBlue(maIntColor.getZ().getVal());
273 if(mbModifyColor)
275 rColor = mrProcessor.getBColorModifierStack().getModifiedColor(rColor);
279 return fOpacity;
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();
303 if(mbUseTex)
305 if(mbHasTexCoor)
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);
324 if(mbUseNrm)
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);
334 if(mbUseCol)
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;
347 public:
348 ZBufferRasterConverter3D(basegfx::BZPixelRaster& rBuffer, const drawinglayer::processor3d::ZBufferProcessor3D& rProcessor)
349 : basegfx::RasterConverter3D(),
350 mrProcessor(rProcessor),
351 mrBuffer(rBuffer),
352 maIntZ(),
353 maIntColor(),
354 maIntNormal(),
355 maIntTexture(),
356 maIntInvTexture(),
357 mpCurrentMaterial(0),
358 mbModifyColor(false),
359 mbUseTex(false),
360 mbHasTexCoor(false),
361 mbHasInvTexCoor(false),
362 mbUseNrm(false),
363 mbUseCol(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()))));
381 if(nXA < nXB)
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;
395 while(nXA < nXB)
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));
402 if(nNewZ > rOldZ)
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)));
407 if(nOpacity > 0)
409 // avoid color overrun
410 aNewColor.clamp();
412 if(nOpacity >= 0x00ff)
414 // full opacity (not transparent), set z and color
415 rOldZ = nNewZ;
416 mrBuffer.getBPixel(nScanlineIndex) = basegfx::BPixel(aNewColor, 0xff);
418 else
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());
438 else
440 // dest is unused, set color
441 rDest = basegfx::BPixel(aNewColor, (sal_uInt8)nOpacity);
447 // increments
448 nScanlineIndex++;
449 nXA++;
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
468 private:
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;
473 double mfCenterZ;
475 // bitfield
476 bool mbModulate : 1;
477 bool mbFilter : 1;
478 bool mbSimpleTextureActive : 1;
479 bool mbIsLine : 1;
481 public:
482 RasterPrimitive3D(
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,
487 bool bModulate,
488 bool bFilter,
489 bool bSimpleTextureActive,
490 bool bIsLine)
491 : mpGeoTexSvx(pGeoTexSvx),
492 mpTransparenceGeoTexSvx(pTransparenceGeoTexSvx),
493 maMaterial(rMaterial),
494 maPolyPolygon(rPolyPolygon),
495 mfCenterZ(basegfx::tools::getRange(rPolyPolygon).getCenter().getZ()),
496 mbModulate(bModulate),
497 mbFilter(bFilter),
498 mbSimpleTextureActive(bSimpleTextureActive),
499 mbIsLine(bIsLine)
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;
515 return *this;
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
539 if(mpBZPixelRaster)
541 if(getTransparenceCounter())
543 // transparent output; record for later sorting and painting from
544 // back to front
545 if(!mpRasterPrimitive3Ds)
547 const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds = new std::vector< RasterPrimitive3D >;
550 mpRasterPrimitive3Ds->push_back(RasterPrimitive3D(
551 getGeoTexSvx(),
552 getTransparenceGeoTexSvx(),
553 rMaterial,
554 basegfx::B3DPolyPolygon(rHairline),
555 getModulate(),
556 getFilter(),
557 getSimpleTextureActive(),
558 true));
560 else
562 // do rasterconversion
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 aSnappedHairline.transform(aTransform);
589 mpZBufferRasterConverter3D->rasterconvertB3DPolygon(aSnappedHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize);
591 else
593 mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize);
596 else
598 mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), 1);
604 void ZBufferProcessor3D::rasterconvertB3DPolyPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolyPolygon& rFill) const
606 if(mpBZPixelRaster)
608 if(getTransparenceCounter())
610 // transparent output; record for later sorting and painting from
611 // back to front
612 if(!mpRasterPrimitive3Ds)
614 const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds = new std::vector< RasterPrimitive3D >;
617 mpRasterPrimitive3Ds->push_back(RasterPrimitive3D(
618 getGeoTexSvx(),
619 getTransparenceGeoTexSvx(),
620 rMaterial,
621 rFill,
622 getModulate(),
623 getFilter(),
624 getSimpleTextureActive(),
625 false));
627 else
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,
640 double fSizeX,
641 double fSizeY,
642 const basegfx::B2DRange& rVisiblePart,
643 sal_uInt16 nAntiAlialize)
644 : DefaultProcessor3D(rViewInformation3D, rSdrSceneAttribute, rSdrLightingAttribute),
645 mpBZPixelRaster(0),
646 maInvEyeToView(),
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;
677 // step one:
679 // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also
680 // necessary to
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);
689 // step two:
691 // bring from [0.0 .. 1.0] in X,Y and Z to view cordinates
693 // #i102611#
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);
704 if(mnAntiAlialize)
705 aDeviceToView.scale(fFullViewSizeX * mnAntiAlialize, fFullViewSizeY * mnAntiAlialize, fMaxZDepth);
706 else
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(),
717 aDeviceToView,
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()
740 if(mpBZPixelRaster)
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());
760 if(nSize > 1)
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
769 // the render method
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));
784 else
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
801 if(mpBZPixelRaster)
803 return BPixelRasterToBitmapEx(*mpBZPixelRaster, mnAntiAlialize);
806 return BitmapEx();
808 } // end of namespace processor3d
809 } // end of namespace drawinglayer
811 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */