blob: 5e0fea27f8379db40c9454e8f93d10671ffd7f06 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef _BGFX_RASTER_RASTERCONVERT3D_HXX
#define _BGFX_RASTER_RASTERCONVERT3D_HXX
#include <sal/types.h>
#include <vector>
#include <basegfx/color/bcolor.hxx>
#include <basegfx/vector/b3dvector.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/vector/b2dvector.hxx>
//////////////////////////////////////////////////////////////////////////////
// predeclarations
namespace basegfx
{
class B3DPolygon;
class B3DPolyPolygon;
}
//////////////////////////////////////////////////////////////////////////////
// interpolators for double precision
namespace basegfx
{
class ip_single
{
private:
double mfVal;
double mfInc;
public:
ip_single()
: mfVal(0.0),
mfInc(0.0)
{}
ip_single(double fVal, double fInc)
: mfVal(fVal),
mfInc(fInc)
{}
double getVal() const { return mfVal; }
double getInc() const { return mfInc; }
void increment(double fStep) { mfVal += fStep * mfInc; }
};
} // end of namespace basegfx
namespace basegfx
{
class ip_double
{
private:
ip_single maX;
ip_single maY;
public:
ip_double()
: maX(),
maY()
{}
ip_double(double fXVal, double fXInc, double fYVal, double fYInc)
: maX(fXVal, fXInc),
maY(fYVal, fYInc)
{}
const ip_single& getX() const { return maX; }
const ip_single& getY() const { return maY; }
void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); }
};
} // end of namespace basegfx
namespace basegfx
{
class ip_triple
{
private:
ip_single maX;
ip_single maY;
ip_single maZ;
public:
ip_triple()
: maX(),
maY(),
maZ()
{}
ip_triple(double fXVal, double fXInc, double fYVal, double fYInc, double fZVal, double fZInc)
: maX(fXVal, fXInc),
maY(fYVal, fYInc),
maZ(fZVal, fZInc)
{}
const ip_single& getX() const { return maX; }
const ip_single& getY() const { return maY; }
const ip_single& getZ() const { return maZ; }
void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); maZ.increment(fStep); }
};
} // end of namespace basegfx
//////////////////////////////////////////////////////////////////////////////
// InterpolatorProvider3D to have a common source for allocating interpolators
// which may then be addressed using the index to the vectors
namespace basegfx
{
#define SCANLINE_EMPTY_INDEX (0xffffffff)
class InterpolatorProvider3D
{
private:
::std::vector< ip_triple > maColorInterpolators;
::std::vector< ip_triple > maNormalInterpolators;
::std::vector< ip_double > maTextureInterpolators;
::std::vector< ip_triple > maInverseTextureInterpolators;
protected:
sal_uInt32 addColorInterpolator(const BColor& rA, const BColor& rB, double fInvYDelta)
{
double aDeltaRed(rB.getRed() - rA.getRed());
if(fTools::equalZero(aDeltaRed))
{
aDeltaRed = 0.0;
}
else
{
aDeltaRed *= fInvYDelta;
}
double aDeltaGreen(rB.getGreen() - rA.getGreen());
if(fTools::equalZero(aDeltaGreen))
{
aDeltaGreen = 0.0;
}
else
{
aDeltaGreen *= fInvYDelta;
}
double aDeltaBlue(rB.getBlue() - rA.getBlue());
if(fTools::equalZero(aDeltaBlue))
{
aDeltaBlue = 0.0;
}
else
{
aDeltaBlue *= fInvYDelta;
}
maColorInterpolators.push_back(
ip_triple(
rA.getRed(), aDeltaRed,
rA.getGreen(), aDeltaGreen,
rA.getBlue(), aDeltaBlue));
return (maColorInterpolators.size() - 1);
}
sal_uInt32 addNormalInterpolator(const B3DVector& rA, const B3DVector& rB, double fInvYDelta)
{
double aDeltaX(rB.getX() - rA.getX());
if(fTools::equalZero(aDeltaX))
{
aDeltaX = 0.0;
}
else
{
aDeltaX *= fInvYDelta;
}
double aDeltaY(rB.getY() - rA.getY());
if(fTools::equalZero(aDeltaY))
{
aDeltaY = 0.0;
}
else
{
aDeltaY *= fInvYDelta;
}
double aDeltaZ(rB.getZ() - rA.getZ());
if(fTools::equalZero(aDeltaZ))
{
aDeltaZ = 0.0;
}
else
{
aDeltaZ *= fInvYDelta;
}
maNormalInterpolators.push_back(
ip_triple(
rA.getX(), aDeltaX,
rA.getY(), aDeltaY,
rA.getZ(), aDeltaZ));
return (maNormalInterpolators.size() - 1);
}
sal_uInt32 addTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fInvYDelta)
{
double aDeltaX(rB.getX() - rA.getX());
if(fTools::equalZero(aDeltaX))
{
aDeltaX = 0.0;
}
else
{
aDeltaX *= fInvYDelta;
}
double aDeltaY(rB.getY() - rA.getY());
if(fTools::equalZero(aDeltaY))
{
aDeltaY = 0.0;
}
else
{
aDeltaY *= fInvYDelta;
}
maTextureInterpolators.push_back(
ip_double(
rA.getX(), aDeltaX,
rA.getY(), aDeltaY));
return (maTextureInterpolators.size() - 1);
}
sal_uInt32 addInverseTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fZEyeA, double fZEyeB, double fInvYDelta)
{
double fZDelta(fZEyeB - fZEyeA);
const double fInvZEyeA(fTools::equalZero(fZEyeA) ? fZEyeA : 1.0 / fZEyeA);
double fInvZEyeB(fInvZEyeA);
if(fTools::equalZero(fZDelta))
{
fZDelta = 0.0;
}
else
{
fInvZEyeB = fTools::equalZero(fZEyeB) ? fZEyeB : 1.0 / fZEyeB;
fZDelta = (fInvZEyeB - fInvZEyeA) * fInvYDelta;
}
const B2DPoint aInvA(rA * fInvZEyeA);
const B2DPoint aInvB(rB * fInvZEyeB);
const double aDeltaX((aInvB.getX() - aInvA.getX()) * fInvYDelta);
const double aDeltaY((aInvB.getY() - aInvA.getY()) * fInvYDelta);
maInverseTextureInterpolators.push_back(
ip_triple(
aInvA.getX(), aDeltaX,
aInvA.getY(), aDeltaY,
fInvZEyeA, fZDelta));
return (maInverseTextureInterpolators.size() - 1);
}
void reset()
{
maColorInterpolators.clear();
maNormalInterpolators.clear();
maTextureInterpolators.clear();
maInverseTextureInterpolators.clear();
}
public:
InterpolatorProvider3D() {}
::std::vector< ip_triple >& getColorInterpolators() { return maColorInterpolators; }
::std::vector< ip_triple >& getNormalInterpolators() { return maNormalInterpolators; }
::std::vector< ip_double >& getTextureInterpolators() { return maTextureInterpolators; }
::std::vector< ip_triple >& getInverseTextureInterpolators() { return maInverseTextureInterpolators; }
};
} // end of namespace basegfx
//////////////////////////////////////////////////////////////////////////////
// RasterConversionLineEntry3D for Raterconversion of 3D PolyPolygons
namespace basegfx
{
class RasterConversionLineEntry3D
{
private:
ip_single maX;
ip_single maZ;
sal_Int32 mnY;
sal_uInt32 mnCount;
sal_uInt32 mnColorIndex;
sal_uInt32 mnNormalIndex;
sal_uInt32 mnTextureIndex;
sal_uInt32 mnInverseTextureIndex;
public:
RasterConversionLineEntry3D(const double& rfX, const double& rfDeltaX, const double& rfZ, const double& rfDeltaZ, sal_Int32 nY, sal_uInt32 nCount)
: maX(rfX, rfDeltaX),
maZ(rfZ, rfDeltaZ),
mnY(nY),
mnCount(nCount),
mnColorIndex(SCANLINE_EMPTY_INDEX),
mnNormalIndex(SCANLINE_EMPTY_INDEX),
mnTextureIndex(SCANLINE_EMPTY_INDEX),
mnInverseTextureIndex(SCANLINE_EMPTY_INDEX)
{}
void setColorIndex(sal_uInt32 nIndex) { mnColorIndex = nIndex; }
void setNormalIndex(sal_uInt32 nIndex) { mnNormalIndex = nIndex; }
void setTextureIndex(sal_uInt32 nIndex) { mnTextureIndex = nIndex; }
void setInverseTextureIndex(sal_uInt32 nIndex) { mnInverseTextureIndex = nIndex; }
bool operator<(const RasterConversionLineEntry3D& rComp) const
{
if(mnY == rComp.mnY)
{
return maX.getVal() < rComp.maX.getVal();
}
return mnY < rComp.mnY;
}
bool decrementRasterConversionLineEntry3D(sal_uInt32 nStep)
{
if(nStep >= mnCount)
{
return false;
}
else
{
mnCount -= nStep;
return true;
}
}
void incrementRasterConversionLineEntry3D(sal_uInt32 nStep, InterpolatorProvider3D& rProvider)
{
const double fStep((double)nStep);
maX.increment(fStep);
maZ.increment(fStep);
mnY += nStep;
if(SCANLINE_EMPTY_INDEX != mnColorIndex)
{
rProvider.getColorInterpolators()[mnColorIndex].increment(fStep);
}
if(SCANLINE_EMPTY_INDEX != mnNormalIndex)
{
rProvider.getNormalInterpolators()[mnNormalIndex].increment(fStep);
}
if(SCANLINE_EMPTY_INDEX != mnTextureIndex)
{
rProvider.getTextureInterpolators()[mnTextureIndex].increment(fStep);
}
if(SCANLINE_EMPTY_INDEX != mnInverseTextureIndex)
{
rProvider.getInverseTextureInterpolators()[mnInverseTextureIndex].increment(fStep);
}
}
// data read access
const ip_single& getX() const { return maX; }
sal_Int32 getY() const { return mnY; }
const ip_single& getZ() const { return maZ; }
sal_uInt32 getColorIndex() const { return mnColorIndex; }
sal_uInt32 getNormalIndex() const { return mnNormalIndex; }
sal_uInt32 getTextureIndex() const { return mnTextureIndex; }
sal_uInt32 getInverseTextureIndex() const { return mnInverseTextureIndex; }
};
} // end of namespace basegfx
//////////////////////////////////////////////////////////////////////////////
// the basic RaterConverter itself. Only one method needs to be overloaded. The
// class itself is strictly virtual
namespace basegfx
{
class RasterConverter3D : public InterpolatorProvider3D
{
private:
// the line entries for an area conversion run
::std::vector< RasterConversionLineEntry3D > maLineEntries;
struct lineComparator
{
bool operator()(const RasterConversionLineEntry3D* pA, const RasterConversionLineEntry3D* pB)
{
OSL_ENSURE(pA && pB, "lineComparator: empty pointer (!)");
return pA->getX().getVal() < pB->getX().getVal();
}
};
void addArea(const B3DPolygon& rFill, const B3DHomMatrix* pViewToEye);
void addArea(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye);
void addEdge(const B3DPolygon& rFill, sal_uInt32 a, sal_uInt32 b, const B3DHomMatrix* pViewToEye);
void rasterconvertB3DArea(sal_Int32 nStartLine, sal_Int32 nStopLine);
void rasterconvertB3DEdge(const B3DPolygon& rLine, sal_uInt32 nA, sal_uInt32 nB, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth);
virtual void processLineSpan(const RasterConversionLineEntry3D& rA, const RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount) = 0;
public:
RasterConverter3D();
virtual ~RasterConverter3D();
void rasterconvertB3DPolyPolygon(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye, sal_Int32 nStartLine, sal_Int32 nStopLine);
void rasterconvertB3DPolygon(const B3DPolygon& rLine, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth);
};
} // end of namespace basegfx
//////////////////////////////////////////////////////////////////////////////
#endif /* _BGFX_RASTER_RASTERCONVERT3D_HXX */