xref: /trunk/main/basegfx/inc/basegfx/raster/rasterconvert3d.hxx (revision 914d351e5f5b84e4342a86d6ab8d4aca7308b9bd)
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