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:
ip_single()55 	    ip_single()
56 	    :	mfVal(0.0),
57 		    mfInc(0.0)
58 	    {}
59 
ip_single(double fVal,double fInc)60 	    ip_single(double fVal, double fInc)
61 	    :	mfVal(fVal),
62 		    mfInc(fInc)
63 	    {}
64 
getVal() const65 	    double getVal() const { return mfVal; }
getInc() const66 	    double getInc() const { return mfInc; }
67 
increment(double fStep)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:
ip_double()81 	    ip_double()
82 	    :	maX(),
83 		    maY()
84 	    {}
85 
ip_double(double fXVal,double fXInc,double fYVal,double fYInc)86 	    ip_double(double fXVal, double fXInc, double fYVal, double fYInc)
87 	    :	maX(fXVal, fXInc),
88 		    maY(fYVal, fYInc)
89 	    {}
90 
getX() const91 	    const ip_single& getX() const { return maX; }
getY() const92 	    const ip_single& getY() const { return maY; }
93 
increment(double fStep)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:
ip_triple()108 	    ip_triple()
109 	    :	maX(),
110 		    maY(),
111 		    maZ()
112 	    {}
113 
ip_triple(double fXVal,double fXInc,double fYVal,double fYInc,double fZVal,double fZInc)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 
getX() const120 	    const ip_single& getX() const { return maX; }
getY() const121 	    const ip_single& getY() const { return maY; }
getZ() const122 	    const ip_single& getZ() const { return maZ; }
123 
increment(double fStep)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:
addColorInterpolator(const BColor & rA,const BColor & rB,double fInvYDelta)145 	    sal_uInt32 addColorInterpolator(const BColor& rA, const BColor& rB, double fInvYDelta)
146 	    {
147             double aDeltaRed(rB.getRed() - rA.getRed());
148 
149             if(fTools::equalZero(aDeltaRed))
150             {
151                 aDeltaRed = 0.0;
152             }
153             else
154             {
155                 aDeltaRed *= fInvYDelta;
156             }
157 
158             double aDeltaGreen(rB.getGreen() - rA.getGreen());
159 
160             if(fTools::equalZero(aDeltaGreen))
161             {
162                 aDeltaGreen = 0.0;
163             }
164             else
165             {
166                 aDeltaGreen *= fInvYDelta;
167             }
168 
169             double aDeltaBlue(rB.getBlue() - rA.getBlue());
170 
171             if(fTools::equalZero(aDeltaBlue))
172             {
173                 aDeltaBlue = 0.0;
174             }
175             else
176             {
177                 aDeltaBlue *= fInvYDelta;
178             }
179 
180 		    maColorInterpolators.push_back(
181                 ip_triple(
182                     rA.getRed(), aDeltaRed,
183                     rA.getGreen(), aDeltaGreen,
184                     rA.getBlue(), aDeltaBlue));
185 
186 		    return (maColorInterpolators.size() - 1);
187 	    }
188 
addNormalInterpolator(const B3DVector & rA,const B3DVector & rB,double fInvYDelta)189 	    sal_uInt32 addNormalInterpolator(const B3DVector& rA, const B3DVector& rB, double fInvYDelta)
190 	    {
191             double aDeltaX(rB.getX() - rA.getX());
192 
193             if(fTools::equalZero(aDeltaX))
194             {
195                 aDeltaX = 0.0;
196             }
197             else
198             {
199                 aDeltaX *= fInvYDelta;
200             }
201 
202             double aDeltaY(rB.getY() - rA.getY());
203 
204             if(fTools::equalZero(aDeltaY))
205             {
206                 aDeltaY = 0.0;
207             }
208             else
209             {
210                 aDeltaY *= fInvYDelta;
211             }
212 
213             double aDeltaZ(rB.getZ() - rA.getZ());
214 
215             if(fTools::equalZero(aDeltaZ))
216             {
217                 aDeltaZ = 0.0;
218             }
219             else
220             {
221                 aDeltaZ *= fInvYDelta;
222             }
223 
224 		    maNormalInterpolators.push_back(
225                 ip_triple(
226                     rA.getX(), aDeltaX,
227                     rA.getY(), aDeltaY,
228                     rA.getZ(), aDeltaZ));
229 
230 		    return (maNormalInterpolators.size() - 1);
231 	    }
232 
addTextureInterpolator(const B2DPoint & rA,const B2DPoint & rB,double fInvYDelta)233 	    sal_uInt32 addTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fInvYDelta)
234 	    {
235             double aDeltaX(rB.getX() - rA.getX());
236 
237             if(fTools::equalZero(aDeltaX))
238             {
239                 aDeltaX = 0.0;
240             }
241             else
242             {
243                 aDeltaX *= fInvYDelta;
244             }
245 
246             double aDeltaY(rB.getY() - rA.getY());
247 
248             if(fTools::equalZero(aDeltaY))
249             {
250                 aDeltaY = 0.0;
251             }
252             else
253             {
254                 aDeltaY *= fInvYDelta;
255             }
256 
257 		    maTextureInterpolators.push_back(
258                 ip_double(
259                     rA.getX(), aDeltaX,
260                     rA.getY(), aDeltaY));
261 
262 		    return (maTextureInterpolators.size() - 1);
263 	    }
264 
addInverseTextureInterpolator(const B2DPoint & rA,const B2DPoint & rB,double fZEyeA,double fZEyeB,double fInvYDelta)265 	    sal_uInt32 addInverseTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fZEyeA, double fZEyeB, double fInvYDelta)
266 	    {
267             double fZDelta(fZEyeB - fZEyeA);
268             const double fInvZEyeA(fTools::equalZero(fZEyeA) ? fZEyeA : 1.0 / fZEyeA);
269             double fInvZEyeB(fInvZEyeA);
270 
271             if(fTools::equalZero(fZDelta))
272             {
273                 fZDelta = 0.0;
274             }
275             else
276             {
277                 fInvZEyeB = fTools::equalZero(fZEyeB) ? fZEyeB : 1.0 / fZEyeB;
278                 fZDelta = (fInvZEyeB - fInvZEyeA) * fInvYDelta;
279             }
280 
281             const B2DPoint aInvA(rA * fInvZEyeA);
282             const B2DPoint aInvB(rB * fInvZEyeB);
283             const double aDeltaX((aInvB.getX() - aInvA.getX()) * fInvYDelta);
284             const double aDeltaY((aInvB.getY() - aInvA.getY()) * fInvYDelta);
285 
286 		    maInverseTextureInterpolators.push_back(
287                 ip_triple(
288                     aInvA.getX(), aDeltaX,
289                     aInvA.getY(), aDeltaY,
290                     fInvZEyeA, fZDelta));
291 
292 		    return (maInverseTextureInterpolators.size() - 1);
293 	    }
294 
reset()295 	    void reset()
296 	    {
297 		    maColorInterpolators.clear();
298 		    maNormalInterpolators.clear();
299 		    maTextureInterpolators.clear();
300 		    maInverseTextureInterpolators.clear();
301 	    }
302 
303     public:
InterpolatorProvider3D()304 	    InterpolatorProvider3D() {}
305 
getColorInterpolators()306 	    ::std::vector< ip_triple >& getColorInterpolators() { return maColorInterpolators; }
getNormalInterpolators()307 	    ::std::vector< ip_triple >& getNormalInterpolators() { return maNormalInterpolators; }
getTextureInterpolators()308 	    ::std::vector< ip_double >& getTextureInterpolators() { return maTextureInterpolators; }
getInverseTextureInterpolators()309 	    ::std::vector< ip_triple >& getInverseTextureInterpolators() { return maInverseTextureInterpolators; }
310     };
311 } // end of namespace basegfx
312 
313 //////////////////////////////////////////////////////////////////////////////
314 // RasterConversionLineEntry3D for Raterconversion of 3D PolyPolygons
315 
316 namespace basegfx
317 {
318     class RasterConversionLineEntry3D
319     {
320     private:
321 	    ip_single									maX;
322 	    ip_single									maZ;
323 	    sal_Int32									mnY;
324 	    sal_uInt32									mnCount;
325 
326 	    sal_uInt32									mnColorIndex;
327 	    sal_uInt32									mnNormalIndex;
328 	    sal_uInt32									mnTextureIndex;
329 	    sal_uInt32									mnInverseTextureIndex;
330 
331     public:
RasterConversionLineEntry3D(const double & rfX,const double & rfDeltaX,const double & rfZ,const double & rfDeltaZ,sal_Int32 nY,sal_uInt32 nCount)332 	    RasterConversionLineEntry3D(const double& rfX, const double& rfDeltaX, const double& rfZ, const double& rfDeltaZ, sal_Int32 nY, sal_uInt32 nCount)
333 	    :	maX(rfX, rfDeltaX),
334 		    maZ(rfZ, rfDeltaZ),
335 		    mnY(nY),
336 		    mnCount(nCount),
337 		    mnColorIndex(SCANLINE_EMPTY_INDEX),
338 		    mnNormalIndex(SCANLINE_EMPTY_INDEX),
339 		    mnTextureIndex(SCANLINE_EMPTY_INDEX),
340 		    mnInverseTextureIndex(SCANLINE_EMPTY_INDEX)
341 	    {}
342 
setColorIndex(sal_uInt32 nIndex)343 	    void setColorIndex(sal_uInt32 nIndex) { mnColorIndex = nIndex; }
setNormalIndex(sal_uInt32 nIndex)344 	    void setNormalIndex(sal_uInt32 nIndex) { mnNormalIndex = nIndex; }
setTextureIndex(sal_uInt32 nIndex)345 	    void setTextureIndex(sal_uInt32 nIndex) { mnTextureIndex = nIndex; }
setInverseTextureIndex(sal_uInt32 nIndex)346 	    void setInverseTextureIndex(sal_uInt32 nIndex) { mnInverseTextureIndex = nIndex; }
347 
operator <(const RasterConversionLineEntry3D & rComp) const348 	    bool operator<(const RasterConversionLineEntry3D& rComp) const
349 	    {
350 		    if(mnY == rComp.mnY)
351 		    {
352 			    return maX.getVal() < rComp.maX.getVal();
353 		    }
354 
355 		    return mnY < rComp.mnY;
356 	    }
357 
decrementRasterConversionLineEntry3D(sal_uInt32 nStep)358 	    bool decrementRasterConversionLineEntry3D(sal_uInt32 nStep)
359 	    {
360 		    if(nStep >= mnCount)
361 		    {
362 			    return false;
363 		    }
364 		    else
365 		    {
366 			    mnCount -= nStep;
367 			    return true;
368 		    }
369 	    }
370 
incrementRasterConversionLineEntry3D(sal_uInt32 nStep,InterpolatorProvider3D & rProvider)371 	    void incrementRasterConversionLineEntry3D(sal_uInt32 nStep, InterpolatorProvider3D& rProvider)
372 	    {
373 		    const double fStep((double)nStep);
374 		    maX.increment(fStep);
375 		    maZ.increment(fStep);
376 		    mnY += nStep;
377 
378 		    if(SCANLINE_EMPTY_INDEX != mnColorIndex)
379 		    {
380 			    rProvider.getColorInterpolators()[mnColorIndex].increment(fStep);
381 		    }
382 
383 		    if(SCANLINE_EMPTY_INDEX != mnNormalIndex)
384 		    {
385 			    rProvider.getNormalInterpolators()[mnNormalIndex].increment(fStep);
386 		    }
387 
388 		    if(SCANLINE_EMPTY_INDEX != mnTextureIndex)
389 		    {
390 			    rProvider.getTextureInterpolators()[mnTextureIndex].increment(fStep);
391 		    }
392 
393 		    if(SCANLINE_EMPTY_INDEX != mnInverseTextureIndex)
394 		    {
395 			    rProvider.getInverseTextureInterpolators()[mnInverseTextureIndex].increment(fStep);
396 		    }
397 	    }
398 
399 	    // data read access
getX() const400 	    const ip_single& getX() const { return maX; }
getY() const401 	    sal_Int32 getY() const { return mnY; }
getZ() const402 	    const ip_single& getZ() const { return maZ; }
getColorIndex() const403 	    sal_uInt32 getColorIndex() const { return mnColorIndex; }
getNormalIndex() const404 	    sal_uInt32 getNormalIndex() const { return mnNormalIndex; }
getTextureIndex() const405 	    sal_uInt32 getTextureIndex() const { return mnTextureIndex; }
getInverseTextureIndex() const406 	    sal_uInt32 getInverseTextureIndex() const { return mnInverseTextureIndex; }
407     };
408 } // end of namespace basegfx
409 
410 //////////////////////////////////////////////////////////////////////////////
411 // the basic RaterConverter itself. Only one method needs to be overloaded. The
412 // class itself is strictly virtual
413 
414 namespace basegfx
415 {
416     class RasterConverter3D : public InterpolatorProvider3D
417     {
418     private:
419         // the line entries for an area conversion run
420 	    ::std::vector< RasterConversionLineEntry3D >			maLineEntries;
421 
422 	    struct lineComparator
423 	    {
operator ()basegfx::RasterConverter3D::lineComparator424 		    bool operator()(const RasterConversionLineEntry3D* pA, const RasterConversionLineEntry3D* pB)
425 		    {
426 			    OSL_ENSURE(pA && pB, "lineComparator: empty pointer (!)");
427 			    return pA->getX().getVal() < pB->getX().getVal();
428 		    }
429 	    };
430 
431 	    void addArea(const B3DPolygon& rFill, const B3DHomMatrix* pViewToEye);
432 	    void addArea(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye);
433 	    void addEdge(const B3DPolygon& rFill, sal_uInt32 a, sal_uInt32 b, const B3DHomMatrix* pViewToEye);
434 
435         void rasterconvertB3DArea(sal_Int32 nStartLine, sal_Int32 nStopLine);
436 	    void rasterconvertB3DEdge(const B3DPolygon& rLine, sal_uInt32 nA, sal_uInt32 nB, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth);
437 
438         virtual void processLineSpan(const RasterConversionLineEntry3D& rA, const RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount) = 0;
439 
440     public:
441 	    RasterConverter3D();
442         virtual ~RasterConverter3D();
443 
444 	    void rasterconvertB3DPolyPolygon(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye, sal_Int32 nStartLine, sal_Int32 nStopLine);
445 	    void rasterconvertB3DPolygon(const B3DPolygon& rLine, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth);
446     };
447 } // end of namespace basegfx
448 
449 //////////////////////////////////////////////////////////////////////////////
450 
451 #endif /* _BGFX_RASTER_RASTERCONVERT3D_HXX */
452