xref: /trunk/main/drawinglayer/source/attribute/sdrlightingattribute3d.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  *  OpenOffice.org - a multi-platform office productivity suite
4  *
5  *  $RCSfile: sdrattribute3d.cxx,v $
6  *
7  *  $Revision: 1.5 $
8  *
9  *  last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
10  *
11  *  The Contents of this file are made available subject to
12  *  the terms of GNU Lesser General Public License Version 2.1.
13  *
14  *
15  *    GNU Lesser General Public License Version 2.1
16  *    =============================================
17  *    Copyright 2005 by Sun Microsystems, Inc.
18  *    901 San Antonio Road, Palo Alto, CA 94303, USA
19  *
20  *    This library is free software; you can redistribute it and/or
21  *    modify it under the terms of the GNU Lesser General Public
22  *    License version 2.1, as published by the Free Software Foundation.
23  *
24  *    This library is distributed in the hope that it will be useful,
25  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
26  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27  *    Lesser General Public License for more details.
28  *
29  *    You should have received a copy of the GNU Lesser General Public
30  *    License along with this library; if not, write to the Free Software
31  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32  *    MA  02111-1307  USA
33  *
34  ************************************************************************/
35 
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_drawinglayer.hxx"
38 
39 #include <drawinglayer/attribute/sdrlightingattribute3d.hxx>
40 #include <basegfx/color/bcolor.hxx>
41 #include <basegfx/vector/b3dvector.hxx>
42 #include <drawinglayer/attribute/sdrlightattribute3d.hxx>
43 
44 //////////////////////////////////////////////////////////////////////////////
45 
46 namespace drawinglayer
47 {
48     namespace attribute
49     {
50         class ImpSdrLightingAttribute
51         {
52         public:
53             // refcounter
54             sal_uInt32                              mnRefCount;
55 
56             // 3D light attribute definitions
57             basegfx::BColor                         maAmbientLight;
58             ::std::vector< Sdr3DLightAttribute >    maLightVector;
59 
60             ImpSdrLightingAttribute(
61                 const basegfx::BColor& rAmbientLight,
62                 const ::std::vector< Sdr3DLightAttribute >& rLightVector)
63             :   mnRefCount(0),
64                 maAmbientLight(rAmbientLight),
65                 maLightVector(rLightVector)
66             {
67             }
68 
69             // data read access
70             const basegfx::BColor& getAmbientLight() const { return maAmbientLight; }
71             const ::std::vector< Sdr3DLightAttribute >& getLightVector() const { return maLightVector; }
72 
73             bool operator==(const ImpSdrLightingAttribute& rCandidate) const
74             {
75                 return (getAmbientLight() == rCandidate.getAmbientLight()
76                     && getLightVector() == rCandidate.getLightVector());
77             }
78 
79             static ImpSdrLightingAttribute* get_global_default()
80             {
81                 static ImpSdrLightingAttribute* pDefault = 0;
82 
83                 if(!pDefault)
84                 {
85                     pDefault = new ImpSdrLightingAttribute(
86                         basegfx::BColor(),
87                         std::vector< Sdr3DLightAttribute >());
88 
89                     // never delete; start with RefCount 1, not 0
90                     pDefault->mnRefCount++;
91                 }
92 
93                 return pDefault;
94             }
95         };
96 
97         SdrLightingAttribute::SdrLightingAttribute(
98             const basegfx::BColor& rAmbientLight,
99             const ::std::vector< Sdr3DLightAttribute >& rLightVector)
100         :   mpSdrLightingAttribute(new ImpSdrLightingAttribute(
101                 rAmbientLight, rLightVector))
102         {
103         }
104 
105         SdrLightingAttribute::SdrLightingAttribute()
106         :   mpSdrLightingAttribute(ImpSdrLightingAttribute::get_global_default())
107         {
108             mpSdrLightingAttribute->mnRefCount++;
109         }
110 
111         SdrLightingAttribute::SdrLightingAttribute(const SdrLightingAttribute& rCandidate)
112         :   mpSdrLightingAttribute(rCandidate.mpSdrLightingAttribute)
113         {
114             mpSdrLightingAttribute->mnRefCount++;
115         }
116 
117         SdrLightingAttribute::~SdrLightingAttribute()
118         {
119             if(mpSdrLightingAttribute->mnRefCount)
120             {
121                 mpSdrLightingAttribute->mnRefCount--;
122             }
123             else
124             {
125                 delete mpSdrLightingAttribute;
126             }
127         }
128 
129         bool SdrLightingAttribute::isDefault() const
130         {
131             return mpSdrLightingAttribute == ImpSdrLightingAttribute::get_global_default();
132         }
133 
134         SdrLightingAttribute& SdrLightingAttribute::operator=(const SdrLightingAttribute& rCandidate)
135         {
136             if(rCandidate.mpSdrLightingAttribute != mpSdrLightingAttribute)
137             {
138                 if(mpSdrLightingAttribute->mnRefCount)
139                 {
140                     mpSdrLightingAttribute->mnRefCount--;
141                 }
142                 else
143                 {
144                     delete mpSdrLightingAttribute;
145                 }
146 
147                 mpSdrLightingAttribute = rCandidate.mpSdrLightingAttribute;
148                 mpSdrLightingAttribute->mnRefCount++;
149             }
150 
151             return *this;
152         }
153 
154         bool SdrLightingAttribute::operator==(const SdrLightingAttribute& rCandidate) const
155         {
156             if(rCandidate.mpSdrLightingAttribute == mpSdrLightingAttribute)
157             {
158                 return true;
159             }
160 
161             if(rCandidate.isDefault() != isDefault())
162             {
163                 return false;
164             }
165 
166             return (*rCandidate.mpSdrLightingAttribute == *mpSdrLightingAttribute);
167         }
168 
169         const basegfx::BColor& SdrLightingAttribute::getAmbientLight() const
170         {
171             return mpSdrLightingAttribute->getAmbientLight();
172         }
173 
174         const ::std::vector< Sdr3DLightAttribute >& SdrLightingAttribute::getLightVector() const
175         {
176             return mpSdrLightingAttribute->getLightVector();
177         }
178 
179         // color model solver
180         basegfx::BColor SdrLightingAttribute::solveColorModel(
181             const basegfx::B3DVector& rNormalInEyeCoordinates,
182             const basegfx::BColor& rColor, const basegfx::BColor& rSpecular,
183             const basegfx::BColor& rEmission, sal_uInt16 nSpecularIntensity) const
184         {
185             // initialize with emissive color
186             basegfx::BColor aRetval(rEmission);
187 
188             // take care of global ambient light
189             aRetval += mpSdrLightingAttribute->getAmbientLight() * rColor;
190 
191             // prepare light access. Is there a light?
192             const sal_uInt32 nLightCount(mpSdrLightingAttribute->getLightVector().size());
193 
194             if(nLightCount && !rNormalInEyeCoordinates.equalZero())
195             {
196                 // prepare normal
197                 basegfx::B3DVector aEyeNormal(rNormalInEyeCoordinates);
198                 aEyeNormal.normalize();
199 
200                 for(sal_uInt32 a(0L); a < nLightCount; a++)
201                 {
202                     const Sdr3DLightAttribute& rLight(mpSdrLightingAttribute->getLightVector()[a]);
203                     const double fCosFac(rLight.getDirection().scalar(aEyeNormal));
204 
205                     if(basegfx::fTools::more(fCosFac, 0.0))
206                     {
207                         aRetval += ((rLight.getColor() * rColor) * fCosFac);
208 
209                         if(rLight.getSpecular())
210                         {
211                             // expand by (0.0, 0.0, 1.0) in Z
212                             basegfx::B3DVector aSpecularNormal(rLight.getDirection().getX(), rLight.getDirection().getY(), rLight.getDirection().getZ() + 1.0);
213                             aSpecularNormal.normalize();
214                             double fCosFac2(aSpecularNormal.scalar(aEyeNormal));
215 
216                             if(basegfx::fTools::more(fCosFac2, 0.0))
217                             {
218                                 fCosFac2 = pow(fCosFac2, (double)nSpecularIntensity);
219                                 aRetval += (rSpecular * fCosFac2);
220                             }
221                         }
222                     }
223                 }
224             }
225 
226             // clamp to color space before usage
227             aRetval.clamp();
228 
229             return aRetval;
230         }
231     } // end of namespace attribute
232 } // end of namespace drawinglayer
233 
234 //////////////////////////////////////////////////////////////////////////////
235 // eof
236