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