blob: 1cc52db4fe16d04cb87fb0daa90b0b6aa55370be [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.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_drawinglayer.hxx"
#include <drawinglayer/attribute/sdrlightingattribute3d.hxx>
#include <basegfx/color/bcolor.hxx>
#include <basegfx/vector/b3dvector.hxx>
#include <drawinglayer/attribute/sdrlightattribute3d.hxx>
//////////////////////////////////////////////////////////////////////////////
namespace drawinglayer
{
namespace attribute
{
class ImpSdrLightingAttribute
{
public:
// refcounter
sal_uInt32 mnRefCount;
// 3D light attribute definitions
basegfx::BColor maAmbientLight;
::std::vector< Sdr3DLightAttribute > maLightVector;
ImpSdrLightingAttribute(
const basegfx::BColor& rAmbientLight,
const ::std::vector< Sdr3DLightAttribute >& rLightVector)
: mnRefCount(0),
maAmbientLight(rAmbientLight),
maLightVector(rLightVector)
{
}
// data read access
const basegfx::BColor& getAmbientLight() const { return maAmbientLight; }
const ::std::vector< Sdr3DLightAttribute >& getLightVector() const { return maLightVector; }
bool operator==(const ImpSdrLightingAttribute& rCandidate) const
{
return (getAmbientLight() == rCandidate.getAmbientLight()
&& getLightVector() == rCandidate.getLightVector());
}
static ImpSdrLightingAttribute* get_global_default()
{
static ImpSdrLightingAttribute* pDefault = 0;
if(!pDefault)
{
pDefault = new ImpSdrLightingAttribute(
basegfx::BColor(),
std::vector< Sdr3DLightAttribute >());
// never delete; start with RefCount 1, not 0
pDefault->mnRefCount++;
}
return pDefault;
}
};
SdrLightingAttribute::SdrLightingAttribute(
const basegfx::BColor& rAmbientLight,
const ::std::vector< Sdr3DLightAttribute >& rLightVector)
: mpSdrLightingAttribute(new ImpSdrLightingAttribute(
rAmbientLight, rLightVector))
{
}
SdrLightingAttribute::SdrLightingAttribute()
: mpSdrLightingAttribute(ImpSdrLightingAttribute::get_global_default())
{
mpSdrLightingAttribute->mnRefCount++;
}
SdrLightingAttribute::SdrLightingAttribute(const SdrLightingAttribute& rCandidate)
: mpSdrLightingAttribute(rCandidate.mpSdrLightingAttribute)
{
mpSdrLightingAttribute->mnRefCount++;
}
SdrLightingAttribute::~SdrLightingAttribute()
{
if(mpSdrLightingAttribute->mnRefCount)
{
mpSdrLightingAttribute->mnRefCount--;
}
else
{
delete mpSdrLightingAttribute;
}
}
bool SdrLightingAttribute::isDefault() const
{
return mpSdrLightingAttribute == ImpSdrLightingAttribute::get_global_default();
}
SdrLightingAttribute& SdrLightingAttribute::operator=(const SdrLightingAttribute& rCandidate)
{
if(rCandidate.mpSdrLightingAttribute != mpSdrLightingAttribute)
{
if(mpSdrLightingAttribute->mnRefCount)
{
mpSdrLightingAttribute->mnRefCount--;
}
else
{
delete mpSdrLightingAttribute;
}
mpSdrLightingAttribute = rCandidate.mpSdrLightingAttribute;
mpSdrLightingAttribute->mnRefCount++;
}
return *this;
}
bool SdrLightingAttribute::operator==(const SdrLightingAttribute& rCandidate) const
{
if(rCandidate.mpSdrLightingAttribute == mpSdrLightingAttribute)
{
return true;
}
if(rCandidate.isDefault() != isDefault())
{
return false;
}
return (*rCandidate.mpSdrLightingAttribute == *mpSdrLightingAttribute);
}
const basegfx::BColor& SdrLightingAttribute::getAmbientLight() const
{
return mpSdrLightingAttribute->getAmbientLight();
}
const ::std::vector< Sdr3DLightAttribute >& SdrLightingAttribute::getLightVector() const
{
return mpSdrLightingAttribute->getLightVector();
}
// color model solver
basegfx::BColor SdrLightingAttribute::solveColorModel(
const basegfx::B3DVector& rNormalInEyeCoordinates,
const basegfx::BColor& rColor, const basegfx::BColor& rSpecular,
const basegfx::BColor& rEmission, sal_uInt16 nSpecularIntensity) const
{
// initialize with emissive color
basegfx::BColor aRetval(rEmission);
// take care of global ambient light
aRetval += mpSdrLightingAttribute->getAmbientLight() * rColor;
// prepare light access. Is there a light?
const sal_uInt32 nLightCount(mpSdrLightingAttribute->getLightVector().size());
if(nLightCount && !rNormalInEyeCoordinates.equalZero())
{
// prepare normal
basegfx::B3DVector aEyeNormal(rNormalInEyeCoordinates);
aEyeNormal.normalize();
for(sal_uInt32 a(0L); a < nLightCount; a++)
{
const Sdr3DLightAttribute& rLight(mpSdrLightingAttribute->getLightVector()[a]);
const double fCosFac(rLight.getDirection().scalar(aEyeNormal));
if(basegfx::fTools::more(fCosFac, 0.0))
{
aRetval += ((rLight.getColor() * rColor) * fCosFac);
if(rLight.getSpecular())
{
// expand by (0.0, 0.0, 1.0) in Z
basegfx::B3DVector aSpecularNormal(rLight.getDirection().getX(), rLight.getDirection().getY(), rLight.getDirection().getZ() + 1.0);
aSpecularNormal.normalize();
double fCosFac2(aSpecularNormal.scalar(aEyeNormal));
if(basegfx::fTools::more(fCosFac2, 0.0))
{
fCosFac2 = pow(fCosFac2, (double)nSpecularIntensity);
aRetval += (rSpecular * fCosFac2);
}
}
}
}
}
// clamp to color space before usage
aRetval.clamp();
return aRetval;
}
} // end of namespace attribute
} // end of namespace drawinglayer
//////////////////////////////////////////////////////////////////////////////
// eof