1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef _BGFX_RASTER_RASTERCONVERT3D_HXX
29 #define _BGFX_RASTER_RASTERCONVERT3D_HXX
30 
31 #include <sal/types.h>
32 #include <vector>
33 #include <basegfx/color/bcolor.hxx>
34 #include <basegfx/vector/b3dvector.hxx>
35 #include <basegfx/point/b2dpoint.hxx>
36 #include <basegfx/vector/b2dvector.hxx>
37 
38 //////////////////////////////////////////////////////////////////////////////
39 // predeclarations
40 
41 namespace basegfx
42 {
43     class B3DPolygon;
44     class B3DPolyPolygon;
45 }
46 
47 //////////////////////////////////////////////////////////////////////////////
48 // interpolators for double precision
49 
50 namespace basegfx
51 {
52     class ip_single
53     {
54     private:
55 	    double										mfVal;
56 	    double										mfInc;
57 
58     public:
59 	    ip_single()
60 	    :	mfVal(0.0),
61 		    mfInc(0.0)
62 	    {}
63 
64 	    ip_single(double fVal, double fInc)
65 	    :	mfVal(fVal),
66 		    mfInc(fInc)
67 	    {}
68 
69 	    double getVal() const { return mfVal; }
70 	    double getInc() const { return mfInc; }
71 
72 	    void increment(double fStep) { mfVal += fStep * mfInc; }
73     };
74 } // end of namespace basegfx
75 
76 namespace basegfx
77 {
78     class ip_double
79     {
80     private:
81 	    ip_single									maX;
82 	    ip_single									maY;
83 
84     public:
85 	    ip_double()
86 	    :	maX(),
87 		    maY()
88 	    {}
89 
90 	    ip_double(double fXVal, double fXInc, double fYVal, double fYInc)
91 	    :	maX(fXVal, fXInc),
92 		    maY(fYVal, fYInc)
93 	    {}
94 
95 	    const ip_single& getX() const { return maX; }
96 	    const ip_single& getY() const { return maY; }
97 
98 	    void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); }
99     };
100 } // end of namespace basegfx
101 
102 namespace basegfx
103 {
104     class ip_triple
105     {
106     private:
107 	    ip_single									maX;
108 	    ip_single									maY;
109 	    ip_single									maZ;
110 
111     public:
112 	    ip_triple()
113 	    :	maX(),
114 		    maY(),
115 		    maZ()
116 	    {}
117 
118 	    ip_triple(double fXVal, double fXInc, double fYVal, double fYInc, double fZVal, double fZInc)
119 	    :	maX(fXVal, fXInc),
120 		    maY(fYVal, fYInc),
121 		    maZ(fZVal, fZInc)
122 	    {}
123 
124 	    const ip_single& getX() const { return maX; }
125 	    const ip_single& getY() const { return maY; }
126 	    const ip_single& getZ() const { return maZ; }
127 
128 	    void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); maZ.increment(fStep); }
129     };
130 } // end of namespace basegfx
131 
132 //////////////////////////////////////////////////////////////////////////////
133 // InterpolatorProvider3D to have a common source for allocating interpolators
134 // which may then be addressed using the index to the vectors
135 
136 namespace basegfx
137 {
138     #define	SCANLINE_EMPTY_INDEX (0xffffffff)
139 
140     class InterpolatorProvider3D
141     {
142     private:
143 	    ::std::vector< ip_triple >					maColorInterpolators;
144 	    ::std::vector< ip_triple >					maNormalInterpolators;
145 	    ::std::vector< ip_double >					maTextureInterpolators;
146 	    ::std::vector< ip_triple >					maInverseTextureInterpolators;
147 
148     protected:
149 	    sal_uInt32 addColorInterpolator(const BColor& rA, const BColor& rB, double fInvYDelta)
150 	    {
151 		    B3DVector aDelta(rB.getRed() - rA.getRed(), rB.getGreen() - rA.getGreen(), rB.getBlue() - rA.getBlue());
152 		    aDelta *= fInvYDelta;
153 		    maColorInterpolators.push_back(ip_triple(rA.getRed(), aDelta.getX(), rA.getGreen(), aDelta.getY(), rA.getBlue(), aDelta.getZ()));
154 		    return (maColorInterpolators.size() - 1L);
155 	    }
156 
157 	    sal_uInt32 addNormalInterpolator(const B3DVector& rA, const B3DVector& rB, double fInvYDelta)
158 	    {
159 		    B3DVector aDelta(rB.getX() - rA.getX(), rB.getY() - rA.getY(), rB.getZ() - rA.getZ());
160 		    aDelta *= fInvYDelta;
161 		    maNormalInterpolators.push_back(ip_triple(rA.getX(), aDelta.getX(), rA.getY(), aDelta.getY(), rA.getZ(), aDelta.getZ()));
162 		    return (maNormalInterpolators.size() - 1L);
163 	    }
164 
165 	    sal_uInt32 addTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fInvYDelta)
166 	    {
167 		    B2DVector aDelta(rB.getX() - rA.getX(), rB.getY() - rA.getY());
168 		    aDelta *= fInvYDelta;
169 		    maTextureInterpolators.push_back(ip_double(rA.getX(), aDelta.getX(), rA.getY(), aDelta.getY()));
170 		    return (maTextureInterpolators.size() - 1L);
171 	    }
172 
173 	    sal_uInt32 addInverseTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fZEyeA, double fZEyeB, double fInvYDelta)
174 	    {
175 		    const double fInvZEyeA(fTools::equalZero(fZEyeA) ? fZEyeA : 1.0 / fZEyeA);
176 		    const double fInvZEyeB(fTools::equalZero(fZEyeB) ? fZEyeB : 1.0 / fZEyeB);
177 		    const B2DPoint aInvA(rA * fInvZEyeA);
178 		    const B2DPoint aInvB(rB * fInvZEyeB);
179 		    double fZDelta(fInvZEyeB - fInvZEyeA);
180 		    B2DVector aDelta(aInvB.getX() - aInvA.getX(), aInvB.getY() - aInvA.getY());
181 
182 		    fZDelta *= fInvYDelta;
183 		    aDelta *= fInvYDelta;
184 
185 		    maInverseTextureInterpolators.push_back(ip_triple(aInvA.getX(), aDelta.getX(), aInvA.getY(), aDelta.getY(), fInvZEyeA, fZDelta));
186 		    return (maInverseTextureInterpolators.size() - 1L);
187 	    }
188 
189 	    void reset()
190 	    {
191 		    maColorInterpolators.clear();
192 		    maNormalInterpolators.clear();
193 		    maTextureInterpolators.clear();
194 		    maInverseTextureInterpolators.clear();
195 	    }
196 
197     public:
198 	    InterpolatorProvider3D() {}
199 
200 	    ::std::vector< ip_triple >& getColorInterpolators() { return maColorInterpolators; }
201 	    ::std::vector< ip_triple >& getNormalInterpolators() { return maNormalInterpolators; }
202 	    ::std::vector< ip_double >& getTextureInterpolators() { return maTextureInterpolators; }
203 	    ::std::vector< ip_triple >& getInverseTextureInterpolators() { return maInverseTextureInterpolators; }
204     };
205 } // end of namespace basegfx
206 
207 //////////////////////////////////////////////////////////////////////////////
208 // RasterConversionLineEntry3D for Raterconversion of 3D PolyPolygons
209 
210 namespace basegfx
211 {
212     class RasterConversionLineEntry3D
213     {
214     private:
215 	    ip_single									maX;
216 	    ip_single									maZ;
217 	    sal_Int32									mnY;
218 	    sal_uInt32									mnCount;
219 
220 	    sal_uInt32									mnColorIndex;
221 	    sal_uInt32									mnNormalIndex;
222 	    sal_uInt32									mnTextureIndex;
223 	    sal_uInt32									mnInverseTextureIndex;
224 
225     public:
226 	    RasterConversionLineEntry3D(const double& rfX, const double& rfDeltaX, const double& rfZ, const double& rfDeltaZ, sal_Int32 nY, sal_uInt32 nCount)
227 	    :	maX(rfX, rfDeltaX),
228 		    maZ(rfZ, rfDeltaZ),
229 		    mnY(nY),
230 		    mnCount(nCount),
231 		    mnColorIndex(SCANLINE_EMPTY_INDEX),
232 		    mnNormalIndex(SCANLINE_EMPTY_INDEX),
233 		    mnTextureIndex(SCANLINE_EMPTY_INDEX),
234 		    mnInverseTextureIndex(SCANLINE_EMPTY_INDEX)
235 	    {}
236 
237 	    void setColorIndex(sal_uInt32 nIndex) { mnColorIndex = nIndex; }
238 	    void setNormalIndex(sal_uInt32 nIndex) { mnNormalIndex = nIndex; }
239 	    void setTextureIndex(sal_uInt32 nIndex) { mnTextureIndex = nIndex; }
240 	    void setInverseTextureIndex(sal_uInt32 nIndex) { mnInverseTextureIndex = nIndex; }
241 
242 	    bool operator<(const RasterConversionLineEntry3D& rComp) const
243 	    {
244 		    if(mnY == rComp.mnY)
245 		    {
246 			    return maX.getVal() < rComp.maX.getVal();
247 		    }
248 
249 		    return mnY < rComp.mnY;
250 	    }
251 
252 	    bool decrementRasterConversionLineEntry3D(sal_uInt32 nStep)
253 	    {
254 		    if(nStep >= mnCount)
255 		    {
256 			    return false;
257 		    }
258 		    else
259 		    {
260 			    mnCount -= nStep;
261 			    return true;
262 		    }
263 	    }
264 
265 	    void incrementRasterConversionLineEntry3D(sal_uInt32 nStep, InterpolatorProvider3D& rProvider)
266 	    {
267 		    const double fStep((double)nStep);
268 		    maX.increment(fStep);
269 		    maZ.increment(fStep);
270 		    mnY += nStep;
271 
272 		    if(SCANLINE_EMPTY_INDEX != mnColorIndex)
273 		    {
274 			    rProvider.getColorInterpolators()[mnColorIndex].increment(fStep);
275 		    }
276 
277 		    if(SCANLINE_EMPTY_INDEX != mnNormalIndex)
278 		    {
279 			    rProvider.getNormalInterpolators()[mnNormalIndex].increment(fStep);
280 		    }
281 
282 		    if(SCANLINE_EMPTY_INDEX != mnTextureIndex)
283 		    {
284 			    rProvider.getTextureInterpolators()[mnTextureIndex].increment(fStep);
285 		    }
286 
287 		    if(SCANLINE_EMPTY_INDEX != mnInverseTextureIndex)
288 		    {
289 			    rProvider.getInverseTextureInterpolators()[mnInverseTextureIndex].increment(fStep);
290 		    }
291 	    }
292 
293 	    // data read access
294 	    const ip_single& getX() const { return maX; }
295 	    sal_Int32 getY() const { return mnY; }
296 	    const ip_single& getZ() const { return maZ; }
297 	    sal_uInt32 getColorIndex() const { return mnColorIndex; }
298 	    sal_uInt32 getNormalIndex() const { return mnNormalIndex; }
299 	    sal_uInt32 getTextureIndex() const { return mnTextureIndex; }
300 	    sal_uInt32 getInverseTextureIndex() const { return mnInverseTextureIndex; }
301     };
302 } // end of namespace basegfx
303 
304 //////////////////////////////////////////////////////////////////////////////
305 // the basic RaterConverter itself. Only one method needs to be overloaded. The
306 // class itself is strictly virtual
307 
308 namespace basegfx
309 {
310     class RasterConverter3D : public InterpolatorProvider3D
311     {
312     private:
313         // the line entries for an area conversion run
314 	    ::std::vector< RasterConversionLineEntry3D >			maLineEntries;
315 
316 	    struct lineComparator
317 	    {
318 		    bool operator()(const RasterConversionLineEntry3D* pA, const RasterConversionLineEntry3D* pB)
319 		    {
320 			    OSL_ENSURE(pA && pB, "lineComparator: empty pointer (!)");
321 			    return pA->getX().getVal() < pB->getX().getVal();
322 		    }
323 	    };
324 
325 	    void addArea(const B3DPolygon& rFill, const B3DHomMatrix* pViewToEye);
326 	    void addArea(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye);
327 	    void addEdge(const B3DPolygon& rFill, sal_uInt32 a, sal_uInt32 b, const B3DHomMatrix* pViewToEye);
328 
329         void rasterconvertB3DArea(sal_Int32 nStartLine, sal_Int32 nStopLine);
330 	    void rasterconvertB3DEdge(const B3DPolygon& rLine, sal_uInt32 nA, sal_uInt32 nB, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth);
331 
332         virtual void processLineSpan(const RasterConversionLineEntry3D& rA, const RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount) = 0;
333 
334     public:
335 	    RasterConverter3D();
336         virtual ~RasterConverter3D();
337 
338 	    void rasterconvertB3DPolyPolygon(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye, sal_Int32 nStartLine, sal_Int32 nStopLine);
339 	    void rasterconvertB3DPolygon(const B3DPolygon& rLine, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth);
340     };
341 } // end of namespace basegfx
342 
343 //////////////////////////////////////////////////////////////////////////////
344 
345 #endif /* _BGFX_RASTER_RASTERCONVERT3D_HXX */
346