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