Use COMReference to handle COM pointers in CreateShortcut
[LibreOffice.git] / drawinglayer / source / processor3d / zbufferprocessor3d.cxx
blob82c1129fa5853d2d25095657ae9de9db2fd7708e
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 <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>
30 #include <o3tl/safeint.hxx>
31 #include <svtools/optionsdrawinglayer.hxx>
32 #include <utility>
34 using namespace com::sun::star;
36 class ZBufferRasterConverter3D : public basegfx::RasterConverter3D
38 private:
39 const drawinglayer::processor3d::DefaultProcessor3D& mrProcessor;
40 basegfx::BZPixelRaster& mrBuffer;
42 // interpolators for a single line span
43 basegfx::ip_single maIntZ;
44 basegfx::ip_triple maIntColor;
45 basegfx::ip_triple maIntNormal;
46 basegfx::ip_double maIntTexture;
47 basegfx::ip_triple maIntInvTexture;
49 // current material to use for rasterconversion
50 const drawinglayer::attribute::MaterialAttribute3D* mpCurrentMaterial;
52 // some boolean flags for line span interpolator usages
53 bool mbModifyColor : 1;
54 bool mbUseTex : 1;
55 bool mbHasTexCoor : 1;
56 bool mbHasInvTexCoor : 1;
57 bool mbUseNrm : 1;
58 bool mbUseCol : 1;
60 void getTextureCoor(basegfx::B2DPoint& rTarget) const
62 if(mbHasTexCoor)
64 rTarget.setX(maIntTexture.getX().getVal());
65 rTarget.setY(maIntTexture.getY().getVal());
67 else if(mbHasInvTexCoor)
69 const double fZFactor(maIntInvTexture.getZ().getVal());
70 const double fInvZFactor(basegfx::fTools::equalZero(fZFactor) ? 1.0 : 1.0 / fZFactor);
71 rTarget.setX(maIntInvTexture.getX().getVal() * fInvZFactor);
72 rTarget.setY(maIntInvTexture.getY().getVal() * fInvZFactor);
76 void incrementLineSpanInterpolators(double fStep)
78 maIntZ.increment(fStep);
80 if(mbUseTex)
82 if(mbHasTexCoor)
84 maIntTexture.increment(fStep);
86 else if(mbHasInvTexCoor)
88 maIntInvTexture.increment(fStep);
92 if(mbUseNrm)
94 maIntNormal.increment(fStep);
97 if(mbUseCol)
99 maIntColor.increment(fStep);
103 double decideColorAndOpacity(basegfx::BColor& rColor) const
105 // init values with full opacity and material color
106 assert(nullptr != mpCurrentMaterial && "CurrentMaterial not set (!)");
107 double fOpacity(1.0);
108 rColor = mpCurrentMaterial->getColor();
110 if(mbUseTex)
112 basegfx::B2DPoint aTexCoor(0.0, 0.0);
113 getTextureCoor(aTexCoor);
115 if(mrProcessor.getGeoTexSvx())
117 // calc color in spot. This may also set to invisible already when
118 // e.g. bitmap textures have transparent parts
119 mrProcessor.getGeoTexSvx()->modifyBColor(aTexCoor, rColor, fOpacity);
122 if (fOpacity > 0.0 && !basegfx::fTools::equalZero(fOpacity) && mrProcessor.getTransparenceGeoTexSvx())
124 // calc opacity. Object has a 2nd texture, a transparence texture
125 mrProcessor.getTransparenceGeoTexSvx()->modifyOpacity(aTexCoor, fOpacity);
129 if (fOpacity > 0.0 && !basegfx::fTools::equalZero(fOpacity))
131 if(mrProcessor.getGeoTexSvx())
133 if(mbUseNrm)
135 // blend texture with phong
136 rColor = mrProcessor.getSdrLightingAttribute().solveColorModel(
137 basegfx::B3DVector(maIntNormal.getX().getVal(), maIntNormal.getY().getVal(), maIntNormal.getZ().getVal()),
138 rColor,
139 mpCurrentMaterial->getSpecular(),
140 mpCurrentMaterial->getEmission(),
141 mpCurrentMaterial->getSpecularIntensity());
143 else if(mbUseCol)
145 // blend texture with gouraud
146 basegfx::BColor aBlendColor(maIntColor.getX().getVal(), maIntColor.getY().getVal(), maIntColor.getZ().getVal());
147 rColor *= aBlendColor;
149 else if(mrProcessor.getModulate())
151 // blend texture with single material color
152 rColor *= mpCurrentMaterial->getColor();
155 else
157 if(mbUseNrm)
159 // modify color with phong
160 rColor = mrProcessor.getSdrLightingAttribute().solveColorModel(
161 basegfx::B3DVector(maIntNormal.getX().getVal(), maIntNormal.getY().getVal(), maIntNormal.getZ().getVal()),
162 rColor,
163 mpCurrentMaterial->getSpecular(),
164 mpCurrentMaterial->getEmission(),
165 mpCurrentMaterial->getSpecularIntensity());
167 else if(mbUseCol)
169 // modify color with gouraud
170 rColor.setRed(maIntColor.getX().getVal());
171 rColor.setGreen(maIntColor.getY().getVal());
172 rColor.setBlue(maIntColor.getZ().getVal());
176 if(mbModifyColor)
178 rColor = mrProcessor.getBColorModifierStack().getModifiedColor(rColor);
182 return fOpacity;
185 void setupLineSpanInterpolators(const basegfx::RasterConversionLineEntry3D& rA, const basegfx::RasterConversionLineEntry3D& rB)
187 // get inverse XDelta
188 const double xInvDelta(1.0 / (rB.getX().getVal() - rA.getX().getVal()));
190 // prepare Z-interpolator
191 const double fZA(rA.getZ().getVal());
192 const double fZB(rB.getZ().getVal());
193 maIntZ = basegfx::ip_single(fZA, (fZB - fZA) * xInvDelta);
195 // get bools and init other interpolators on demand accordingly
196 mbModifyColor = mrProcessor.getBColorModifierStack().count();
197 mbHasTexCoor = SCANLINE_EMPTY_INDEX != rA.getTextureIndex() && SCANLINE_EMPTY_INDEX != rB.getTextureIndex();
198 mbHasInvTexCoor = SCANLINE_EMPTY_INDEX != rA.getInverseTextureIndex() && SCANLINE_EMPTY_INDEX != rB.getInverseTextureIndex();
199 const bool bTextureActive(mrProcessor.getGeoTexSvx() || mrProcessor.getTransparenceGeoTexSvx());
200 mbUseTex = bTextureActive && (mbHasTexCoor || mbHasInvTexCoor || mrProcessor.getSimpleTextureActive());
201 const bool bUseColorTex(mbUseTex && mrProcessor.getGeoTexSvx());
202 const bool bNeedNrmOrCol(!bUseColorTex || mrProcessor.getModulate());
203 mbUseNrm = bNeedNrmOrCol && SCANLINE_EMPTY_INDEX != rA.getNormalIndex() && SCANLINE_EMPTY_INDEX != rB.getNormalIndex();
204 mbUseCol = !mbUseNrm && bNeedNrmOrCol && SCANLINE_EMPTY_INDEX != rA.getColorIndex() && SCANLINE_EMPTY_INDEX != rB.getColorIndex();
206 if(mbUseTex)
208 if(mbHasTexCoor)
210 const basegfx::ip_double& rTA(getTextureInterpolators()[rA.getTextureIndex()]);
211 const basegfx::ip_double& rTB(getTextureInterpolators()[rB.getTextureIndex()]);
212 maIntTexture = basegfx::ip_double(
213 rTA.getX().getVal(), (rTB.getX().getVal() - rTA.getX().getVal()) * xInvDelta,
214 rTA.getY().getVal(), (rTB.getY().getVal() - rTA.getY().getVal()) * xInvDelta);
216 else if(mbHasInvTexCoor)
218 const basegfx::ip_triple& rITA(getInverseTextureInterpolators()[rA.getInverseTextureIndex()]);
219 const basegfx::ip_triple& rITB(getInverseTextureInterpolators()[rB.getInverseTextureIndex()]);
220 maIntInvTexture = basegfx::ip_triple(
221 rITA.getX().getVal(), (rITB.getX().getVal() - rITA.getX().getVal()) * xInvDelta,
222 rITA.getY().getVal(), (rITB.getY().getVal() - rITA.getY().getVal()) * xInvDelta,
223 rITA.getZ().getVal(), (rITB.getZ().getVal() - rITA.getZ().getVal()) * xInvDelta);
227 if(mbUseNrm)
229 const basegfx::ip_triple& rNA(getNormalInterpolators()[rA.getNormalIndex()]);
230 const basegfx::ip_triple& rNB(getNormalInterpolators()[rB.getNormalIndex()]);
231 maIntNormal = basegfx::ip_triple(
232 rNA.getX().getVal(), (rNB.getX().getVal() - rNA.getX().getVal()) * xInvDelta,
233 rNA.getY().getVal(), (rNB.getY().getVal() - rNA.getY().getVal()) * xInvDelta,
234 rNA.getZ().getVal(), (rNB.getZ().getVal() - rNA.getZ().getVal()) * xInvDelta);
237 if(mbUseCol)
239 const basegfx::ip_triple& rCA(getColorInterpolators()[rA.getColorIndex()]);
240 const basegfx::ip_triple& rCB(getColorInterpolators()[rB.getColorIndex()]);
241 maIntColor = basegfx::ip_triple(
242 rCA.getX().getVal(), (rCB.getX().getVal() - rCA.getX().getVal()) * xInvDelta,
243 rCA.getY().getVal(), (rCB.getY().getVal() - rCA.getY().getVal()) * xInvDelta,
244 rCA.getZ().getVal(), (rCB.getZ().getVal() - rCA.getZ().getVal()) * xInvDelta);
248 virtual void processLineSpan(const basegfx::RasterConversionLineEntry3D& rA, const basegfx::RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount) override;
250 public:
251 ZBufferRasterConverter3D(basegfx::BZPixelRaster& rBuffer, const drawinglayer::processor3d::ZBufferProcessor3D& rProcessor)
252 : mrProcessor(rProcessor),
253 mrBuffer(rBuffer),
254 mpCurrentMaterial(nullptr),
255 mbModifyColor(false),
256 mbUseTex(false),
257 mbHasTexCoor(false),
258 mbHasInvTexCoor(false),
259 mbUseNrm(false),
260 mbUseCol(false)
263 void setCurrentMaterial(const drawinglayer::attribute::MaterialAttribute3D& rMaterial)
265 mpCurrentMaterial = &rMaterial;
269 void ZBufferRasterConverter3D::processLineSpan(const basegfx::RasterConversionLineEntry3D& rA, const basegfx::RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount)
271 if(nSpanCount & 0x0001)
272 return;
274 if(nLine < 0 || o3tl::make_unsigned(nLine) >= mrBuffer.getHeight())
275 return;
277 sal_uInt32 nXA(std::min(mrBuffer.getWidth(), static_cast<sal_uInt32>(std::max(sal_Int32(0), basegfx::fround(rA.getX().getVal())))));
278 const sal_uInt32 nXB(std::min(mrBuffer.getWidth(), static_cast<sal_uInt32>(std::max(sal_Int32(0), basegfx::fround(rB.getX().getVal())))));
280 if(nXA >= nXB)
281 return;
283 // prepare the span interpolators
284 setupLineSpanInterpolators(rA, rB);
286 // bring span interpolators to start condition by incrementing with the possible difference of
287 // clamped and non-clamped XStart. Interpolators are setup relying on double precision
288 // X-values, so that difference is the correct value to compensate for possible clampings
289 incrementLineSpanInterpolators(static_cast<double>(nXA) - rA.getX().getVal());
291 // prepare scanline index
292 sal_uInt32 nScanlineIndex(mrBuffer.getIndexFromXY(nXA, static_cast<sal_uInt32>(nLine)));
293 basegfx::BColor aNewColor;
295 while(nXA < nXB)
297 // early-test Z values if we need to do anything at all
298 const double fNewZ(std::clamp(maIntZ.getVal(), 0.0, 65535.0));
299 const sal_uInt16 nNewZ(static_cast< sal_uInt16 >(fNewZ));
300 sal_uInt16& rOldZ(mrBuffer.getZ(nScanlineIndex));
302 if(nNewZ > rOldZ)
304 // detect color and opacity for this pixel
305 const sal_uInt16 nOpacity(std::max(sal_Int16(0), static_cast< sal_Int16 >(decideColorAndOpacity(aNewColor) * 255.0)));
307 if(nOpacity > 0)
309 // avoid color overrun
310 aNewColor.clamp();
312 if(nOpacity >= 0x00ff)
314 // full opacity (not transparent), set z and color
315 rOldZ = nNewZ;
316 mrBuffer.getBPixel(nScanlineIndex) = basegfx::BPixel(aNewColor, 0xff);
318 else
320 basegfx::BPixel& rDest = mrBuffer.getBPixel(nScanlineIndex);
322 if(rDest.getAlpha())
324 // mix new color by using
325 // color' = color * (1 - opacity) + newcolor * opacity
326 const sal_uInt16 nTransparence(255 - nOpacity);
327 rDest.setRed(static_cast<sal_uInt8>(((rDest.getRed() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getRed()) * nOpacity)) >> 8));
328 rDest.setGreen(static_cast<sal_uInt8>(((rDest.getGreen() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getGreen()) * nOpacity)) >> 8));
329 rDest.setBlue(static_cast<sal_uInt8>(((rDest.getBlue() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getBlue()) * nOpacity)) >> 8));
331 if(255 != rDest.getAlpha())
333 // both are transparent, mix new opacity by using
334 // opacity = newopacity * (1 - oldopacity) + oldopacity
335 rDest.setAlpha(static_cast<sal_uInt8>((nOpacity * (255 - rDest.getAlpha())) >> 8) + rDest.getAlpha());
338 else
340 // dest is unused, set color
341 rDest = basegfx::BPixel(aNewColor, static_cast<sal_uInt8>(nOpacity));
347 // increments
348 nScanlineIndex++;
349 nXA++;
350 incrementLineSpanInterpolators(1.0);
354 // helper class to buffer output for transparent rasterprimitives (filled areas
355 // and lines) until the end of processing. To ensure correct transparent
356 // visualisation, ZBuffers require to not set Z and to mix with the transparent
357 // color. If transparent rasterprimitives overlap, it gets necessary to
358 // paint transparent rasterprimitives from back to front to ensure that the
359 // mixing happens from back to front. For that purpose, transparent
360 // rasterprimitives are held in this class during the processing run, remember
361 // all data and will be rendered
363 class RasterPrimitive3D
365 private:
366 std::shared_ptr< drawinglayer::texture::GeoTexSvx > mpGeoTexSvx;
367 std::shared_ptr< drawinglayer::texture::GeoTexSvx > mpTransparenceGeoTexSvx;
368 drawinglayer::attribute::MaterialAttribute3D maMaterial;
369 basegfx::B3DPolyPolygon maPolyPolygon;
370 double mfCenterZ;
372 bool mbModulate : 1;
373 bool mbFilter : 1;
374 bool mbSimpleTextureActive : 1;
375 bool mbIsLine : 1;
377 public:
378 RasterPrimitive3D(
379 std::shared_ptr< drawinglayer::texture::GeoTexSvx > pGeoTexSvx,
380 std::shared_ptr< drawinglayer::texture::GeoTexSvx > pTransparenceGeoTexSvx,
381 const drawinglayer::attribute::MaterialAttribute3D& rMaterial,
382 const basegfx::B3DPolyPolygon& rPolyPolygon,
383 bool bModulate,
384 bool bFilter,
385 bool bSimpleTextureActive,
386 bool bIsLine)
387 : mpGeoTexSvx(std::move(pGeoTexSvx)),
388 mpTransparenceGeoTexSvx(std::move(pTransparenceGeoTexSvx)),
389 maMaterial(rMaterial),
390 maPolyPolygon(rPolyPolygon),
391 mfCenterZ(basegfx::utils::getRange(rPolyPolygon).getCenter().getZ()),
392 mbModulate(bModulate),
393 mbFilter(bFilter),
394 mbSimpleTextureActive(bSimpleTextureActive),
395 mbIsLine(bIsLine)
399 bool operator<(const RasterPrimitive3D& rComp) const
401 return mfCenterZ < rComp.mfCenterZ;
404 const std::shared_ptr< drawinglayer::texture::GeoTexSvx >& getGeoTexSvx() const { return mpGeoTexSvx; }
405 const std::shared_ptr< drawinglayer::texture::GeoTexSvx >& getTransparenceGeoTexSvx() const { return mpTransparenceGeoTexSvx; }
406 const drawinglayer::attribute::MaterialAttribute3D& getMaterial() const { return maMaterial; }
407 const basegfx::B3DPolyPolygon& getPolyPolygon() const { return maPolyPolygon; }
408 bool getModulate() const { return mbModulate; }
409 bool getFilter() const { return mbFilter; }
410 bool getSimpleTextureActive() const { return mbSimpleTextureActive; }
411 bool getIsLine() const { return mbIsLine; }
414 namespace drawinglayer::processor3d
416 void ZBufferProcessor3D::rasterconvertB3DPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolygon& rHairline) const
418 if(getTransparenceCounter())
420 // transparent output; record for later sorting and painting from
421 // back to front
423 maRasterPrimitive3Ds.push_back(RasterPrimitive3D(
424 getGeoTexSvx(),
425 getTransparenceGeoTexSvx(),
426 rMaterial,
427 basegfx::B3DPolyPolygon(rHairline),
428 getModulate(),
429 getFilter(),
430 getSimpleTextureActive(),
431 true));
433 else
435 // do rasterconversion
436 mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial);
438 if(mnAntiAlialize > 1)
440 const bool bForceLineSnap(SvtOptionsDrawinglayer::IsAntiAliasing() && SvtOptionsDrawinglayer::IsSnapHorVerLinesToDiscrete());
442 if(bForceLineSnap)
444 basegfx::B3DHomMatrix aTransform;
445 basegfx::B3DPolygon aSnappedHairline(rHairline);
446 const double fScaleDown(1.0 / mnAntiAlialize);
447 const double fScaleUp(mnAntiAlialize);
449 // take oversampling out
450 aTransform.scale(fScaleDown, fScaleDown, 1.0);
451 aSnappedHairline.transform(aTransform);
453 // snap to integer
454 aSnappedHairline = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aSnappedHairline);
456 // add oversampling again
457 aTransform.identity();
458 aTransform.scale(fScaleUp, fScaleUp, 1.0);
460 aSnappedHairline.transform(aTransform);
462 mpZBufferRasterConverter3D->rasterconvertB3DPolygon(aSnappedHairline, mnStartLine, mnStopLine, mnAntiAlialize);
464 else
466 mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, mnStartLine, mnStopLine, mnAntiAlialize);
469 else
471 mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, mnStartLine, mnStopLine, 1);
476 void ZBufferProcessor3D::rasterconvertB3DPolyPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolyPolygon& rFill) const
478 if(getTransparenceCounter())
480 // transparent output; record for later sorting and painting from
481 // back to front
482 maRasterPrimitive3Ds.push_back(RasterPrimitive3D(
483 getGeoTexSvx(),
484 getTransparenceGeoTexSvx(),
485 rMaterial,
486 rFill,
487 getModulate(),
488 getFilter(),
489 getSimpleTextureActive(),
490 false));
492 else
494 mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial);
495 mpZBufferRasterConverter3D->rasterconvertB3DPolyPolygon(rFill, &maInvEyeToView, mnStartLine, mnStopLine);
499 ZBufferProcessor3D::ZBufferProcessor3D(
500 const geometry::ViewInformation3D& rViewInformation3D,
501 const attribute::SdrSceneAttribute& rSdrSceneAttribute,
502 const attribute::SdrLightingAttribute& rSdrLightingAttribute,
503 const basegfx::B2DRange& rVisiblePart,
504 sal_uInt16 nAntiAlialize,
505 double fFullViewSizeX,
506 double fFullViewSizeY,
507 basegfx::BZPixelRaster& rBZPixelRaster,
508 sal_uInt32 nStartLine,
509 sal_uInt32 nStopLine)
510 : DefaultProcessor3D(rViewInformation3D, rSdrSceneAttribute, rSdrLightingAttribute),
511 mnAntiAlialize(nAntiAlialize),
512 mnStartLine(nStartLine),
513 mnStopLine(nStopLine)
515 // create DeviceToView for Z-Buffer renderer since Z is handled
516 // different from standard 3D transformations (Z is mirrored). Also
517 // the transformation includes the step from unit device coordinates
518 // to discrete units ([-1.0 .. 1.0] -> [minDiscrete .. maxDiscrete]
519 basegfx::B3DHomMatrix aDeviceToView;
522 // step one:
524 // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also
525 // necessary to
526 // - flip Y due to screen orientation
527 // - flip Z due to Z-Buffer orientation from back to front
529 aDeviceToView.scale(0.5, -0.5, -0.5);
530 aDeviceToView.translate(0.5, 0.5, 0.5);
534 // step two:
536 // bring from [0.0 .. 1.0] in X,Y and Z to view coordinates
538 // #i102611#
539 // also: scale Z to [1.5 .. 65534.5]. Normally, a range of [0.0 .. 65535.0]
540 // could be used, but a 'unused' value is needed, so '0' is used what reduces
541 // the range to [1.0 .. 65535.0]. It has also shown that small numerical errors
542 // (smaller as basegfx::fTools::mfSmallValue, which is 0.000000001) happen.
543 // Instead of checking those by basegfx::fTools methods which would cost
544 // runtime, just add another 0.5 tolerance to the start and end of the Z-Buffer
545 // range, thus resulting in [1.5 .. 65534.5]
546 const double fMaxZDepth(65533.0);
547 aDeviceToView.translate(-rVisiblePart.getMinX(), -rVisiblePart.getMinY(), 0.0);
549 if(mnAntiAlialize)
550 aDeviceToView.scale(fFullViewSizeX * mnAntiAlialize, fFullViewSizeY * mnAntiAlialize, fMaxZDepth);
551 else
552 aDeviceToView.scale(fFullViewSizeX, fFullViewSizeY, fMaxZDepth);
554 aDeviceToView.translate(0.0, 0.0, 1.5);
557 // update local ViewInformation3D with own DeviceToView
558 const geometry::ViewInformation3D aNewViewInformation3D(
559 getViewInformation3D().getObjectTransformation(),
560 getViewInformation3D().getOrientation(),
561 getViewInformation3D().getProjection(),
562 aDeviceToView,
563 getViewInformation3D().getViewTime(),
564 getViewInformation3D().getExtendedInformationSequence());
565 updateViewInformation(aNewViewInformation3D);
567 // prepare inverse EyeToView transformation. This can be done in constructor
568 // since changes in object transformations when processing TransformPrimitive3Ds
569 // do not influence this prepared partial transformation
570 maInvEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
571 maInvEyeToView.invert();
573 // prepare maRasterRange
574 maRasterRange.reset();
575 maRasterRange.expand(basegfx::B2DPoint(0.0, nStartLine));
576 maRasterRange.expand(basegfx::B2DPoint(rBZPixelRaster.getWidth(), nStopLine));
578 // create the raster converter
579 mpZBufferRasterConverter3D.reset( new ZBufferRasterConverter3D(rBZPixelRaster, *this) );
582 ZBufferProcessor3D::~ZBufferProcessor3D()
584 mpZBufferRasterConverter3D.reset();
586 if(!maRasterPrimitive3Ds.empty())
588 OSL_FAIL("ZBufferProcessor3D: destructed, but there are unrendered transparent geometries. Use ZBufferProcessor3D::finish() to render these (!)");
592 void ZBufferProcessor3D::finish()
594 if(maRasterPrimitive3Ds.empty())
595 return;
597 // there are transparent rasterprimitives
598 const sal_uInt32 nSize(maRasterPrimitive3Ds.size());
600 if(nSize > 1)
602 // sort them from back to front
603 std::sort(maRasterPrimitive3Ds.begin(), maRasterPrimitive3Ds.end());
606 for(sal_uInt32 a(0); a < nSize; a++)
608 // paint each one by setting the remembered data and calling
609 // the render method
610 const RasterPrimitive3D& rCandidate = maRasterPrimitive3Ds[a];
612 mpGeoTexSvx = rCandidate.getGeoTexSvx();
613 mpTransparenceGeoTexSvx = rCandidate.getTransparenceGeoTexSvx();
614 mbModulate = rCandidate.getModulate();
615 mbFilter = rCandidate.getFilter();
616 mbSimpleTextureActive = rCandidate.getSimpleTextureActive();
618 if(rCandidate.getIsLine())
620 rasterconvertB3DPolygon(
621 rCandidate.getMaterial(),
622 rCandidate.getPolyPolygon().getB3DPolygon(0));
624 else
626 rasterconvertB3DPolyPolygon(
627 rCandidate.getMaterial(),
628 rCandidate.getPolyPolygon());
632 // delete them to signal the destructor that all is done and
633 // to allow asserting there
634 maRasterPrimitive3Ds.clear();
637 } // end of namespace
639 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */