diff options
author | Armin Weiss <aw@openoffice.org> | 2006-05-12 10:54:47 +0000 |
---|---|---|
committer | Armin Weiss <aw@openoffice.org> | 2006-05-12 10:54:47 +0000 |
commit | c9ea78f03a45dac9b54a7afa33e069be8a290768 (patch) | |
tree | 633ef301cf53861c987cbcdcba61d499ef270bfc /drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx | |
parent | cb7695b1bf4239f9c24e63e52e98b8c5677e6341 (diff) |
code changes for primitive support
Diffstat (limited to 'drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx')
-rw-r--r-- | drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx | 832 |
1 files changed, 832 insertions, 0 deletions
diff --git a/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx b/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx new file mode 100644 index 000000000000..2a3f4c67d91c --- /dev/null +++ b/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx @@ -0,0 +1,832 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sdrextrudelathetools3d.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: aw $ $Date: 2006-05-12 11:49:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef _DRAWINGLAYER_PRIMITIVE3D_SDREXTRUDELATHETOOLS3D_HXX +#include <drawinglayer/primitive3d/sdrextrudelathetools3d.hxx> +#endif + +#ifndef _BGFX_POLYGON_B2DPOLYPOLYGON_HXX +#include <basegfx/polygon/b2dpolypolygon.hxx> +#endif + +#ifndef _BGFX_RANGE_B2DRANGE_HXX +#include <basegfx/range/b2drange.hxx> +#endif + +#ifndef _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#endif + +#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX +#include <basegfx/matrix/b2dhommatrix.hxx> +#endif + +#ifndef _BGFX_POINT_B3DPOINT_HXX +#include <basegfx/point/b3dpoint.hxx> +#endif + +#ifndef _BGFX_POLYGON_B3DPOLYGON_HXX +#include <basegfx/polygon/b3dpolygon.hxx> +#endif + +#ifndef _BGFX_POLYGON_B3DPOLYGONTOOLS_HXX +#include <basegfx/polygon/b3dpolygontools.hxx> +#endif + +#ifndef _BGFX_POLYPOLYGON_B3DPOLYGONTOOLS_HXX +#include <basegfx/polygon/b3dpolypolygontools.hxx> +#endif + +#ifndef _BGFX_RANGE_B3DRANGE_HXX +#include <basegfx/range/b3drange.hxx> +#endif + +#ifndef _BGFX_MATRIX_B3DHOMMATRIX_HXX +#include <basegfx/matrix/b3dhommatrix.hxx> +#endif + +#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX +#include <basegfx/polygon/b2dpolygontools.hxx> +#endif + +#include <numeric> + +////////////////////////////////////////////////////////////////////////////// +// decompositon helpers for extrude/lathe (rotation) objects + +namespace +{ + ////////////////////////////////////////////////////////////////////////////// + // common helpers + + ::basegfx::B2DPolyPolygon impScalePolyPolygonOnCenter(const ::basegfx::B2DPolyPolygon& rSource, double fScale) + { + ::basegfx::B2DPolyPolygon aRetval(rSource); + + if(!::basegfx::fTools::equalZero(fScale)) + { + const ::basegfx::B2DRange aRange(::basegfx::tools::getRange(rSource)); + const ::basegfx::B2DPoint aCenter(aRange.getCenter()); + ::basegfx::B2DHomMatrix aTrans; + + aTrans.translate(-aCenter.getX(), -aCenter.getY()); + aTrans.scale(fScale, fScale); + aTrans.translate(aCenter.getX(), aCenter.getY()); + aRetval.transform(aTrans); + } + + return aRetval; + } + + void impGetOuterPolyPolygon(::basegfx::B2DPolyPolygon& rPolygon, ::basegfx::B2DPolyPolygon& rOuterPolyPolygon, double fOffset, bool bCharacterMode) + { + rOuterPolyPolygon = rPolygon; + + if(::basegfx::fTools::more(fOffset, 0.0)) + { + if(bCharacterMode) + { + // grow the outside polygon and scale all polygons to original size. This is done + // to avoid a shrink which potentially would lead to self-intersections, but changes + // the original polygon -> not a precision step, so e.g. not usable for charts + const ::basegfx::B2DRange aRange(::basegfx::tools::getRange(rPolygon)); + rPolygon = ::basegfx::tools::growInNormalDirection(rPolygon, fOffset); + const ::basegfx::B2DRange aGrownRange(::basegfx::tools::getRange(rPolygon)); + const double fScaleX(::basegfx::fTools::equalZero(aGrownRange.getWidth()) ? 1.0 : aRange.getWidth() / aGrownRange.getWidth()); + const double fScaleY(::basegfx::fTools::equalZero(aGrownRange.getHeight())? 1.0 : aRange.getHeight() / aGrownRange.getHeight()); + ::basegfx::B2DHomMatrix aScaleTrans; + + aScaleTrans.translate(-aGrownRange.getMinX(), -aGrownRange.getMinY()); + aScaleTrans.scale(fScaleX, fScaleY); + aScaleTrans.translate(aRange.getMinX(), aRange.getMinY()); + rPolygon.transform(aScaleTrans); + rOuterPolyPolygon.transform(aScaleTrans); + } + else + { + // use more precision, shrink the outer polygons. Since this may lead to self-intersections, + // some kind of correction should be applied here after that step + rOuterPolyPolygon = ::basegfx::tools::growInNormalDirection(rPolygon, -fOffset); + ::basegfx::tools::correctGrowShrinkPolygonPair(rPolygon, rOuterPolyPolygon); + } + } + } + + void impAddInBetweenFill(::basegfx::B3DPolyPolygon& rTarget, const ::basegfx::B3DPolyPolygon& rPolA, const ::basegfx::B3DPolyPolygon& rPolB, + double fTexVerStart, double fTexVerStop, bool bCreateNormals, bool bCreateTextureCoordinates) + { + OSL_ENSURE(rPolA.count() == rPolB.count(), "impAddInBetweenFill: unequally sized polygons (!)"); + const sal_uInt32 nPolygonCount(rPolA.count()); + + for(sal_uInt32 a(0L); a < nPolygonCount; a++) + { + const ::basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a)); + const ::basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a)); + OSL_ENSURE(aSubA.count() == aSubB.count(), "impAddInBetweenFill: unequally sized polygons (!)"); + const sal_uInt32 nPointCount(aSubA.count()); + + if(nPointCount) + { + const sal_uInt32 nEdgeCount(aSubA.isClosed() ? nPointCount : nPointCount - 1L); + double fTexHorMultiplicatorA, fTexHorMultiplicatorB; + double fPolygonPosA, fPolygonPosB; + + if(bCreateTextureCoordinates) + { + const double fPolygonLengthA(::basegfx::tools::getLength(aSubA)); + fTexHorMultiplicatorA = ::basegfx::fTools::equalZero(fPolygonLengthA) ? 1.0 : 1.0 / fPolygonLengthA; + + const double fPolygonLengthB(::basegfx::tools::getLength(aSubB)); + fTexHorMultiplicatorB = ::basegfx::fTools::equalZero(fPolygonLengthB) ? 1.0 : 1.0 / fPolygonLengthB; + + fPolygonPosA = fPolygonPosB = 0.0; + } + + for(sal_uInt32 b(0L); b < nEdgeCount; b++) + { + const sal_uInt32 nIndexA(b); + const sal_uInt32 nIndexB((b + 1L) % nPointCount); + + const ::basegfx::B3DPoint aStartA(aSubA.getB3DPoint(nIndexA)); + const ::basegfx::B3DPoint aEndA(aSubA.getB3DPoint(nIndexB)); + const ::basegfx::B3DPoint aStartB(aSubB.getB3DPoint(nIndexA)); + const ::basegfx::B3DPoint aEndB(aSubB.getB3DPoint(nIndexB)); + + ::basegfx::B3DPolygon aNew; + aNew.setClosed(true); + + aNew.append(aStartA); + aNew.append(aStartB); + aNew.append(aEndB); + aNew.append(aEndA); + + if(bCreateNormals) + { + aNew.setNormal(0L, aSubA.getNormal(nIndexA)); + aNew.setNormal(1L, aSubB.getNormal(nIndexA)); + aNew.setNormal(2L, aSubB.getNormal(nIndexB)); + aNew.setNormal(3L, aSubA.getNormal(nIndexB)); + } + + if(bCreateTextureCoordinates) + { + const double fRelTexAL(fPolygonPosA * fTexHorMultiplicatorA); + const double fEdgeLengthA(::basegfx::B3DVector(aEndA - aStartA).getLength()); + fPolygonPosA += fEdgeLengthA; + const double fRelTexAR(fPolygonPosA * fTexHorMultiplicatorA); + + const double fRelTexBL(fPolygonPosB * fTexHorMultiplicatorB); + const double fEdgeLengthB(::basegfx::B3DVector(aEndB - aStartB).getLength()); + fPolygonPosB += fEdgeLengthB; + const double fRelTexBR(fPolygonPosB * fTexHorMultiplicatorB); + + aNew.setTextureCoordinate(0L, ::basegfx::B2DPoint(fRelTexAL, fTexVerStart)); + aNew.setTextureCoordinate(1L, ::basegfx::B2DPoint(fRelTexBL, fTexVerStop)); + aNew.setTextureCoordinate(2L, ::basegfx::B2DPoint(fRelTexBR, fTexVerStop)); + aNew.setTextureCoordinate(3L, ::basegfx::B2DPoint(fRelTexAR, fTexVerStart)); + } + + rTarget.append(aNew); + } + } + } + } + + void impSetNormal(::basegfx::B3DPolyPolygon& rCandidate, const ::basegfx::B3DVector& rNormal) + { + for(sal_uInt32 a(0L); a < rCandidate.count(); a++) + { + ::basegfx::B3DPolygon aSub(rCandidate.getB3DPolygon(a)); + + for(sal_uInt32 b(0L); b < aSub.count(); b++) + { + aSub.setNormal(b, rNormal); + } + + rCandidate.setB3DPolygon(a, aSub); + } + } + + void impCreateInBetweenNormals(::basegfx::B3DPolyPolygon& rPolA, ::basegfx::B3DPolyPolygon& rPolB, bool bSmoothHorizontalNormals) + { + OSL_ENSURE(rPolA.count() == rPolB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)"); + + for(sal_uInt32 a(0L); a < rPolA.count(); a++) + { + ::basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a)); + ::basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a)); + OSL_ENSURE(aSubA.count() == aSubB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)"); + const sal_uInt32 nPointCount(aSubA.count()); + + if(nPointCount) + { + ::basegfx::B3DPoint aPrev(aSubA.getB3DPoint(nPointCount - 1L)); + ::basegfx::B3DPoint aCurrA(aSubA.getB3DPoint(0L)); + const bool bClosed(aSubA.isClosed()); + + for(sal_uInt32 b(0L); b < nPointCount; b++) + { + const sal_uInt32 nIndNext((b + 1L) % nPointCount); + const ::basegfx::B3DPoint aNext(aSubA.getB3DPoint(nIndNext)); + const ::basegfx::B3DPoint aCurrB(aSubB.getB3DPoint(b)); + + // vector to back + ::basegfx::B3DVector aDepth(aCurrB - aCurrA); + aDepth.normalize(); + + // vector to left + ::basegfx::B3DVector aLeft(aPrev - aCurrA); + + if(!bClosed && 0L == b) + { + // correct for non-closed lines + aLeft = aCurrA - aNext; + } + + aLeft.normalize(); + + // create left normal + const ::basegfx::B3DVector aNormalLeft(aDepth.getPerpendicular(aLeft)); + + if(bSmoothHorizontalNormals) + { + // vector to right + ::basegfx::B3DVector aRight(aNext - aCurrA); + + if(!bClosed && b + 1L == nPointCount) + { + // correct for non-closed lines + aRight = aCurrA - aPrev; + } + + aRight.normalize(); + + // create right normal + const ::basegfx::B3DVector aNormalRight(aRight.getPerpendicular(aDepth)); + + // create smoothed in-between normal + ::basegfx::B3DVector aNewNormal(aNormalLeft + aNormalRight); + aNewNormal.normalize(); + + // set as new normal at polygons + aSubA.setNormal(b, aNewNormal); + aSubB.setNormal(b, aNewNormal); + } + else + { + // set aNormalLeft as new normal at polygons + aSubA.setNormal(b, aNormalLeft); + aSubB.setNormal(b, aNormalLeft); + } + + // prepare next step + aPrev = aCurrA; + aCurrA = aNext; + } + + rPolA.setB3DPolygon(a, aSubA); + rPolB.setB3DPolygon(a, aSubB); + } + } + } + + void impMixNormals(::basegfx::B3DPolyPolygon& rPolA, const ::basegfx::B3DPolyPolygon& rPolB, double fWeightA) + { + const double fWeightB(1.0 - fWeightA); + OSL_ENSURE(rPolA.count() == rPolB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)"); + + for(sal_uInt32 a(0L); a < rPolA.count(); a++) + { + ::basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a)); + const ::basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a)); + OSL_ENSURE(aSubA.count() == aSubB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)"); + const sal_uInt32 nPointCount(aSubA.count()); + + for(sal_uInt32 b(0L); b < nPointCount; b++) + { + const ::basegfx::B3DVector aVA(aSubA.getNormal(b) * fWeightA); + const ::basegfx::B3DVector aVB(aSubB.getNormal(b) * fWeightB); + ::basegfx::B3DVector aVNew(aVA + aVB); + aVNew.normalize(); + aSubA.setNormal(b, aVNew); + } + + rPolA.setB3DPolygon(a, aSubA); + } + } + +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive + { + bool createLatheSlices(sliceVector& rSliceVector, const ::basegfx::B2DPolyPolygon& rSource, + double fBackScale, double fDiagonal, double fRotation, sal_uInt32 nSteps, + bool bCharacterMode, bool bCloseFront, bool bCloseBack) + { + bool bClosedRotation(false); + + if(::basegfx::fTools::equalZero(fRotation) || 0L == nSteps) + { + // no rotation or no steps, just one plane + rSliceVector.push_back(slice(rSource, ::basegfx::B3DHomMatrix())); + } + else + { + const bool bBackScale(!::basegfx::fTools::equal(fBackScale, 1.0)); + bClosedRotation = (!bBackScale && ::basegfx::fTools::equal(fRotation, F_2PI)); + ::basegfx::B2DPolyPolygon aFront(rSource); + ::basegfx::B2DPolyPolygon aBack(rSource); + ::basegfx::B3DHomMatrix aTransformBack; + ::basegfx::B2DPolyPolygon aOuterBack; + + if(bClosedRotation) + { + bCloseFront = bCloseBack = false; + } + + if(bBackScale) + { + // avoid null zoom + if(::basegfx::fTools::equalZero(fBackScale)) + { + fBackScale = 0.000001; + } + + // back is scaled compared to front, create scaled version + aBack = impScalePolyPolygonOnCenter(aBack, fBackScale); + } + + if(bCloseFront || bCloseBack) + { + const ::basegfx::B2DRange aBaseRange(::basegfx::tools::getRange(aFront)); + const double fOuterLength(aBaseRange.getMaxX() * fRotation); + const double fInnerLength(aBaseRange.getMinX() * fRotation); + const double fAverageLength((fOuterLength + fInnerLength) * 0.5); + + if(bCloseFront) + { + const double fOffsetLen((fAverageLength / 12.0) * fDiagonal); + ::basegfx::B2DPolyPolygon aOuterFront; + impGetOuterPolyPolygon(aFront, aOuterFront, fOffsetLen, bCharacterMode); + ::basegfx::B3DHomMatrix aTransform; + aTransform.translate(0.0, 0.0, fOffsetLen); + rSliceVector.push_back(slice(aOuterFront, aTransform, SLICETYPE_FRONTCAP)); + } + + if(bCloseBack) + { + const double fOffsetLen((fAverageLength / 12.0) * fDiagonal); + impGetOuterPolyPolygon(aBack, aOuterBack, fOffsetLen, bCharacterMode); + aTransformBack.translate(0.0, 0.0, -fOffsetLen); + aTransformBack.rotate(0.0, fRotation, 0.0); + } + } + + // add start polygon (a = 0L) + if(!bClosedRotation) + { + rSliceVector.push_back(slice(aFront, ::basegfx::B3DHomMatrix())); + } + + // create segments (a + 1 .. nSteps) + const double fStepSize(1.0 / (double)nSteps); + + for(sal_uInt32 a(0L); a < nSteps; a++) + { + const double fStep((double)(a + 1L) * fStepSize); + ::basegfx::B2DPolyPolygon aNewPoly(bBackScale ? ::basegfx::tools::interpolate(aFront, aBack, fStep) : aFront); + ::basegfx::B3DHomMatrix aNewMat; + aNewMat.rotate(0.0, fRotation * fStep, 0.0); + rSliceVector.push_back(slice(aNewPoly, aNewMat)); + } + + if(bCloseBack) + { + rSliceVector.push_back(slice(aOuterBack, aTransformBack, SLICETYPE_BACKCAP)); + } + } + + return bClosedRotation; + } + + void createExtrudeSlices(sliceVector& rSliceVector, const ::basegfx::B2DPolyPolygon& rSource, + double fBackScale, double fDiagonal, double fDepth, + bool bCharacterMode, bool bCloseFront, bool bCloseBack) + { + if(::basegfx::fTools::equalZero(fDepth)) + { + // no depth, just one plane + rSliceVector.push_back(slice(rSource, ::basegfx::B3DHomMatrix())); + } + else + { + // there is depth, create Polygons for front,back and their default depth positions + ::basegfx::B2DPolyPolygon aFront(rSource); + ::basegfx::B2DPolyPolygon aBack(rSource); + const bool bBackScale(!::basegfx::fTools::equal(fBackScale, 1.0)); + double fZFront(fDepth); // default depth for aFront + double fZBack(0.0); // default depth for aBack + ::basegfx::B2DPolyPolygon aOuterBack; + + if(bBackScale) + { + // avoid null zoom + if(::basegfx::fTools::equalZero(fBackScale)) + { + fBackScale = 0.000001; + } + + // aFront is scaled compared to aBack, create scaled version + aFront = impScalePolyPolygonOnCenter(aFront, fBackScale); + } + + if(bCloseFront) + { + const double fOffset(fDepth * fDiagonal * 0.5); + fZFront = fDepth - fOffset; + ::basegfx::B2DPolyPolygon aOuterFront; + impGetOuterPolyPolygon(aFront, aOuterFront, fOffset, bCharacterMode); + ::basegfx::B3DHomMatrix aTransformFront; + aTransformFront.translate(0.0, 0.0, fDepth); + rSliceVector.push_back(slice(aOuterFront, aTransformFront, SLICETYPE_FRONTCAP)); + } + + if(bCloseBack) + { + const double fOffset(fDepth * fDiagonal * 0.5); + fZBack = fOffset; + impGetOuterPolyPolygon(aBack, aOuterBack, fOffset, bCharacterMode); + } + + // add front and back polygons at evtl. changed depths + { + ::basegfx::B3DHomMatrix aTransformA, aTransformB; + + aTransformA.translate(0.0, 0.0, fZFront); + rSliceVector.push_back(slice(aFront, aTransformA)); + + aTransformB.translate(0.0, 0.0, fZBack); + rSliceVector.push_back(slice(aBack, aTransformB)); + } + + if(bCloseBack) + { + rSliceVector.push_back(slice(aOuterBack, ::basegfx::B3DHomMatrix(), SLICETYPE_BACKCAP)); + } + } + } + + void extractLinesFromSlice(::basegfx::B3DPolyPolygon& rLine, const sliceVector& rSliceVector, bool bClosed) + { + const sal_uInt32 nNumSlices(rSliceVector.size()); + + if(nNumSlices) + { + // slices self + for(sal_uInt32 a(0L); a < nNumSlices; a++) + { + rLine.append(rSliceVector[a].getB3DPolyPolygon()); + } + + // horizontal + const ::basegfx::B3DPolyPolygon& aFirstPolyPolygon(rSliceVector[0L].getB3DPolyPolygon()); + const sal_uInt32 nPolygonCount(aFirstPolyPolygon.count()); + + for(sal_uInt32 b(0L); b < nPolygonCount; b++) + { + const ::basegfx::B3DPolygon& aFirstPolygon(aFirstPolyPolygon.getB3DPolygon(0L)); + const sal_uInt32 nPointCount(aFirstPolygon.count()); + + for(sal_uInt32 c(0L); c < nPointCount; c++) + { + ::basegfx::B3DPolygon aNew; + + for(sal_uInt32 d(0L); d < nNumSlices; d++) + { + aNew.append(rSliceVector[d].getB3DPolyPolygon().getB3DPolygon(b).getB3DPoint(c)); + } + + aNew.setClosed(bClosed); + rLine.append(aNew); + } + } + } + } + + void extractPlanesFromSlice(::std::vector< ::basegfx::B3DPolyPolygon >& rFill, const sliceVector& rSliceVector, + bool bCreateNormals, bool bSmoothHorizontalNormals, bool bSmoothNormals, bool bSmoothLids, bool bClosed, + double fSmoothNormalsMix, double fSmoothLidsMix, bool bCreateTextureCoordinates, const ::basegfx::B2DHomMatrix& rTexTransform) + { + const sal_uInt32 nNumSlices(rSliceVector.size()); + + if(nNumSlices) + { + // common parameters + const sal_uInt32 nLoopCount(bClosed ? nNumSlices : nNumSlices - 1L); + ::basegfx::B3DPolyPolygon aEdgeRounding; + sal_uInt32 a; + + // tetxture parameters + double fInvTexHeight(1.0); + double fTexHeightPos(0.0); + double fTexStart(0.0); + double fTexStop(1.0); + ::std::vector<double> aTexHeightArray; + ::basegfx::B3DRange aTexRangeFront; + ::basegfx::B3DRange aTexRangeBack; + + if(bCreateTextureCoordinates) + { + aTexRangeFront = ::basegfx::tools::getRange(rSliceVector[0L].getB3DPolyPolygon()); + aTexRangeBack = ::basegfx::tools::getRange(rSliceVector[nNumSlices - 1L].getB3DPolyPolygon()); + + if(aTexRangeBack.getDepth() > aTexRangeBack.getWidth()) + { + // last polygon is rotated so that depth is bigger than width, exchange X and Z + // for making applyDefaultTextureCoordinatesParallel use Z instead of X for + // horizontal texture coordinate + aTexRangeBack = ::basegfx::B3DRange( + aTexRangeBack.getMinZ(), aTexRangeBack.getMinY(), aTexRangeBack.getMinX(), + aTexRangeBack.getMaxZ(), aTexRangeBack.getMaxY(), aTexRangeBack.getMaxX()); + } + + ::basegfx::B3DPoint aCenter(::basegfx::tools::getRange(rSliceVector[0L].getB3DPolyPolygon()).getCenter()); + + for(sal_uInt32 a(0L); a < nLoopCount; a++) + { + const ::basegfx::B3DPoint aNextCenter(::basegfx::tools::getRange(rSliceVector[(a + 1L) % nNumSlices].getB3DPolyPolygon()).getCenter()); + const double fLength(::basegfx::B3DVector(aNextCenter - aCenter).getLength()); + aTexHeightArray.push_back(fLength); + aCenter = aNextCenter; + } + + const double fTexHeight(::std::accumulate(aTexHeightArray.begin(), aTexHeightArray.end(), 0.0)); + + if(!::basegfx::fTools::equalZero(fTexHeight)) + { + fInvTexHeight = 1.0 / fTexHeight; + } + } + + for(a = 0L; a < nLoopCount; a++) + { + const slice& rSliceA(rSliceVector[a]); + const slice& rSliceB(rSliceVector[(a + 1L) % nNumSlices]); + const bool bAcceptPair(SLICETYPE_REGULAR == rSliceA.getSliceType() && SLICETYPE_REGULAR == rSliceB.getSliceType()); + ::basegfx::B3DPolyPolygon aPolA(rSliceA.getB3DPolyPolygon()); + ::basegfx::B3DPolyPolygon aPolB(rSliceB.getB3DPolyPolygon()); + + if(bAcceptPair) + { + if(bCreateNormals) + { + impCreateInBetweenNormals(aPolB, aPolA, bSmoothHorizontalNormals); + } + + { + const sal_uInt32 nIndPrev((a + nNumSlices - 1L) % nNumSlices); + const slice& rSlicePrev(rSliceVector[nIndPrev]); + ::basegfx::B3DPolyPolygon aPrev(rSlicePrev.getB3DPolyPolygon()); + ::basegfx::B3DPolyPolygon aPolAA(rSliceA.getB3DPolyPolygon()); + + if(SLICETYPE_FRONTCAP == rSlicePrev.getSliceType()) + { + ::basegfx::B3DPolyPolygon aFront(rSlicePrev.getB3DPolyPolygon()); + const bool bHasSlant(aPolAA != aPrev); + + if(bCreateTextureCoordinates) + { + aFront = ::basegfx::tools::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront); + } + + if(bCreateNormals) + { + const ::basegfx::B3DVector aNormal(aFront.count() ? -aFront.getB3DPolygon(0L).getNormal() : ::basegfx::B3DVector(0.0, 0.0, -1.0)); + impSetNormal(aFront, aNormal); + + if(bHasSlant) + { + impCreateInBetweenNormals(aPolAA, aPrev, bSmoothHorizontalNormals); + + if(bSmoothNormals) + { + // smooth and copy + impMixNormals(aPolA, aPolAA, fSmoothNormalsMix); + aPolAA = aPolA; + } + else + { + // take over from surface + aPolAA = aPolA; + } + + if(bSmoothLids) + { + // smooth and copy + impMixNormals(aFront, aPrev, fSmoothLidsMix); + aPrev = aFront; + } + else + { + // take over from front + aPrev = aFront; + } + } + else + { + if(bSmoothNormals) + { + // smooth + impMixNormals(aPolA, aFront, fSmoothNormalsMix); + } + + if(bSmoothLids) + { + // smooth and copy + impMixNormals(aFront, aPolA, fSmoothLidsMix); + aPolA = aFront; + } + } + } + + if(bHasSlant) + { + if(bCreateTextureCoordinates) + { + fTexStart = fTexHeightPos * fInvTexHeight; + fTexStop = (fTexHeightPos - aTexHeightArray[(a + nLoopCount - 1L) % nLoopCount]) * fInvTexHeight; + } + + impAddInBetweenFill(aEdgeRounding, aPolAA, aPrev, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates); + } + + aFront.flip(); + rFill.push_back(aFront); + } + else + { + if(bCreateNormals && bSmoothNormals && (nIndPrev != a + 1L)) + { + impCreateInBetweenNormals(aPolAA, aPrev, bSmoothHorizontalNormals); + impMixNormals(aPolA, aPolAA, 0.5); + } + } + } + + { + const sal_uInt32 nIndNext((a + 2L) % nNumSlices); + const slice& rSliceNext(rSliceVector[nIndNext]); + ::basegfx::B3DPolyPolygon aNext(rSliceNext.getB3DPolyPolygon()); + ::basegfx::B3DPolyPolygon aPolBB(rSliceB.getB3DPolyPolygon()); + + if(SLICETYPE_BACKCAP == rSliceNext.getSliceType()) + { + ::basegfx::B3DPolyPolygon aBack(rSliceNext.getB3DPolyPolygon()); + const bool bHasSlant(aPolBB != aNext); + + if(bCreateTextureCoordinates) + { + aBack = ::basegfx::tools::applyDefaultTextureCoordinatesParallel(aBack, aTexRangeBack); + } + + if(bCreateNormals) + { + const ::basegfx::B3DVector aNormal(aBack.count() ? aBack.getB3DPolygon(0L).getNormal() : ::basegfx::B3DVector(0.0, 0.0, 1.0)); + impSetNormal(aBack, aNormal); + + if(bHasSlant) + { + impCreateInBetweenNormals(aNext, aPolBB, bSmoothHorizontalNormals); + + if(bSmoothNormals) + { + // smooth and copy + impMixNormals(aPolB, aPolBB, fSmoothNormalsMix); + aPolBB = aPolB; + } + else + { + // take over from surface + aPolBB = aPolB; + } + + if(bSmoothLids) + { + // smooth and copy + impMixNormals(aBack, aNext, fSmoothLidsMix); + aNext = aBack; + } + else + { + // take over from back + aNext = aBack; + } + } + else + { + if(bSmoothNormals) + { + // smooth + impMixNormals(aPolB, aBack, fSmoothNormalsMix); + } + + if(bSmoothLids) + { + // smooth and copy + impMixNormals(aBack, aPolB, fSmoothLidsMix); + aPolB = aBack; + } + } + } + + if(bHasSlant) + { + if(bCreateTextureCoordinates) + { + fTexStart = (fTexHeightPos + aTexHeightArray[a] + aTexHeightArray[(a + 1L) % nLoopCount]) * fInvTexHeight; + fTexStop = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight; + } + + impAddInBetweenFill(aEdgeRounding, aNext, aPolBB, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates); + } + + rFill.push_back(aBack); + } + else + { + if(bCreateNormals && bSmoothNormals && (nIndNext != a)) + { + impCreateInBetweenNormals(aNext, aPolBB, bSmoothHorizontalNormals); + impMixNormals(aPolB, aPolBB, 0.5); + } + } + } + + if(bCreateTextureCoordinates) + { + fTexStart = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight; + fTexStop = fTexHeightPos * fInvTexHeight; + } + + impAddInBetweenFill(aEdgeRounding, aPolB, aPolA, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates); + } + + if(bCreateTextureCoordinates) + { + fTexHeightPos += aTexHeightArray[a]; + } + } + + if(bCreateTextureCoordinates) + { + aEdgeRounding.transformTextureCoordiantes(rTexTransform); + } + + for(a = 0L; a < aEdgeRounding.count(); a++) + { + rFill.push_back(::basegfx::B3DPolyPolygon(aEdgeRounding.getB3DPolygon(a))); + } + } + } + + } // end of namespace primitive +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof |