Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef INCLUDED_BASEGFX_RASTER_RASTERCONVERT3D_HXX
21 : #define INCLUDED_BASEGFX_RASTER_RASTERCONVERT3D_HXX
22 :
23 : #include <sal/types.h>
24 : #include <vector>
25 :
26 : #include <osl/diagnose.h>
27 :
28 : #include <basegfx/color/bcolor.hxx>
29 : #include <basegfx/vector/b3dvector.hxx>
30 : #include <basegfx/point/b2dpoint.hxx>
31 : #include <basegfx/vector/b2dvector.hxx>
32 : #include <basegfx/basegfxdllapi.h>
33 :
34 : namespace basegfx
35 : {
36 : class B3DPolygon;
37 : class B3DPolyPolygon;
38 : }
39 :
40 : // interpolators for double precision
41 :
42 : namespace basegfx
43 : {
44 : class ip_single
45 : {
46 : private:
47 : double mfVal;
48 : double mfInc;
49 :
50 : public:
51 156 : ip_single()
52 : : mfVal(0.0),
53 156 : mfInc(0.0)
54 156 : {}
55 :
56 282801 : ip_single(double fVal, double fInc)
57 : : mfVal(fVal),
58 282801 : mfInc(fInc)
59 282801 : {}
60 :
61 7934741 : double getVal() const { return mfVal; }
62 1658 : double getInc() const { return mfInc; }
63 :
64 7020119 : void increment(double fStep) { mfVal += fStep * mfInc; }
65 : };
66 : } // end of namespace basegfx
67 :
68 : namespace basegfx
69 : {
70 : class ip_double
71 : {
72 : private:
73 : ip_single maX;
74 : ip_single maY;
75 :
76 : public:
77 13 : ip_double()
78 : : maX(),
79 13 : maY()
80 13 : {}
81 :
82 0 : ip_double(double fXVal, double fXInc, double fYVal, double fYInc)
83 : : maX(fXVal, fXInc),
84 0 : maY(fYVal, fYInc)
85 0 : {}
86 :
87 0 : const ip_single& getX() const { return maX; }
88 0 : const ip_single& getY() const { return maY; }
89 :
90 0 : void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); }
91 : };
92 : } // end of namespace basegfx
93 :
94 : namespace basegfx
95 : {
96 : class ip_triple
97 : {
98 : private:
99 : ip_single maX;
100 : ip_single maY;
101 : ip_single maZ;
102 :
103 : public:
104 39 : ip_triple()
105 : : maX(),
106 : maY(),
107 39 : maZ()
108 39 : {}
109 :
110 35528 : ip_triple(double fXVal, double fXInc, double fYVal, double fYInc, double fZVal, double fZInc)
111 : : maX(fXVal, fXInc),
112 : maY(fYVal, fYInc),
113 35528 : maZ(fZVal, fZInc)
114 35528 : {}
115 :
116 1083708 : const ip_single& getX() const { return maX; }
117 1083708 : const ip_single& getY() const { return maY; }
118 1083708 : const ip_single& getZ() const { return maZ; }
119 :
120 1085132 : void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); maZ.increment(fStep); }
121 : };
122 : } // end of namespace basegfx
123 :
124 :
125 : // InterpolatorProvider3D to have a common source for allocating interpolators
126 : // which may then be addressed using the index to the vectors
127 :
128 : namespace basegfx
129 : {
130 : #define SCANLINE_EMPTY_INDEX (0xffffffff)
131 :
132 13 : class InterpolatorProvider3D
133 : {
134 : private:
135 : ::std::vector< ip_triple > maColorInterpolators;
136 : ::std::vector< ip_triple > maNormalInterpolators;
137 : ::std::vector< ip_double > maTextureInterpolators;
138 : ::std::vector< ip_triple > maInverseTextureInterpolators;
139 :
140 : protected:
141 656 : sal_uInt32 addColorInterpolator(const BColor& rA, const BColor& rB, double fInvYDelta)
142 : {
143 656 : double aDeltaRed(rB.getRed() - rA.getRed());
144 :
145 656 : if(fTools::equalZero(aDeltaRed))
146 : {
147 411 : aDeltaRed = 0.0;
148 : }
149 : else
150 : {
151 245 : aDeltaRed *= fInvYDelta;
152 : }
153 :
154 656 : double aDeltaGreen(rB.getGreen() - rA.getGreen());
155 :
156 656 : if(fTools::equalZero(aDeltaGreen))
157 : {
158 411 : aDeltaGreen = 0.0;
159 : }
160 : else
161 : {
162 245 : aDeltaGreen *= fInvYDelta;
163 : }
164 :
165 656 : double aDeltaBlue(rB.getBlue() - rA.getBlue());
166 :
167 656 : if(fTools::equalZero(aDeltaBlue))
168 : {
169 271 : aDeltaBlue = 0.0;
170 : }
171 : else
172 : {
173 385 : aDeltaBlue *= fInvYDelta;
174 : }
175 :
176 : maColorInterpolators.push_back(
177 : ip_triple(
178 : rA.getRed(), aDeltaRed,
179 : rA.getGreen(), aDeltaGreen,
180 656 : rA.getBlue(), aDeltaBlue));
181 :
182 656 : return (maColorInterpolators.size() - 1);
183 : }
184 :
185 0 : sal_uInt32 addNormalInterpolator(const B3DVector& rA, const B3DVector& rB, double fInvYDelta)
186 : {
187 0 : double aDeltaX(rB.getX() - rA.getX());
188 :
189 0 : if(fTools::equalZero(aDeltaX))
190 : {
191 0 : aDeltaX = 0.0;
192 : }
193 : else
194 : {
195 0 : aDeltaX *= fInvYDelta;
196 : }
197 :
198 0 : double aDeltaY(rB.getY() - rA.getY());
199 :
200 0 : if(fTools::equalZero(aDeltaY))
201 : {
202 0 : aDeltaY = 0.0;
203 : }
204 : else
205 : {
206 0 : aDeltaY *= fInvYDelta;
207 : }
208 :
209 0 : double aDeltaZ(rB.getZ() - rA.getZ());
210 :
211 0 : if(fTools::equalZero(aDeltaZ))
212 : {
213 0 : aDeltaZ = 0.0;
214 : }
215 : else
216 : {
217 0 : aDeltaZ *= fInvYDelta;
218 : }
219 :
220 : maNormalInterpolators.push_back(
221 : ip_triple(
222 : rA.getX(), aDeltaX,
223 : rA.getY(), aDeltaY,
224 0 : rA.getZ(), aDeltaZ));
225 :
226 0 : return (maNormalInterpolators.size() - 1);
227 : }
228 :
229 0 : sal_uInt32 addTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fInvYDelta)
230 : {
231 0 : double aDeltaX(rB.getX() - rA.getX());
232 :
233 0 : if(fTools::equalZero(aDeltaX))
234 : {
235 0 : aDeltaX = 0.0;
236 : }
237 : else
238 : {
239 0 : aDeltaX *= fInvYDelta;
240 : }
241 :
242 0 : double aDeltaY(rB.getY() - rA.getY());
243 :
244 0 : if(fTools::equalZero(aDeltaY))
245 : {
246 0 : aDeltaY = 0.0;
247 : }
248 : else
249 : {
250 0 : aDeltaY *= fInvYDelta;
251 : }
252 :
253 : maTextureInterpolators.push_back(
254 : ip_double(
255 : rA.getX(), aDeltaX,
256 0 : rA.getY(), aDeltaY));
257 :
258 0 : return (maTextureInterpolators.size() - 1);
259 : }
260 :
261 656 : sal_uInt32 addInverseTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fZEyeA, double fZEyeB, double fInvYDelta)
262 : {
263 656 : double fZDelta(fZEyeB - fZEyeA);
264 656 : const double fInvZEyeA(fTools::equalZero(fZEyeA) ? fZEyeA : 1.0 / fZEyeA);
265 656 : double fInvZEyeB(fInvZEyeA);
266 :
267 656 : if(fTools::equalZero(fZDelta))
268 : {
269 0 : fZDelta = 0.0;
270 : }
271 : else
272 : {
273 656 : fInvZEyeB = fTools::equalZero(fZEyeB) ? fZEyeB : 1.0 / fZEyeB;
274 656 : fZDelta = (fInvZEyeB - fInvZEyeA) * fInvYDelta;
275 : }
276 :
277 656 : const B2DPoint aInvA(rA * fInvZEyeA);
278 1312 : const B2DPoint aInvB(rB * fInvZEyeB);
279 656 : const double aDeltaX((aInvB.getX() - aInvA.getX()) * fInvYDelta);
280 656 : const double aDeltaY((aInvB.getY() - aInvA.getY()) * fInvYDelta);
281 :
282 : maInverseTextureInterpolators.push_back(
283 : ip_triple(
284 : aInvA.getX(), aDeltaX,
285 : aInvA.getY(), aDeltaY,
286 656 : fInvZEyeA, fZDelta));
287 :
288 1312 : return (maInverseTextureInterpolators.size() - 1);
289 : }
290 :
291 18747 : void reset()
292 : {
293 18747 : maColorInterpolators.clear();
294 18747 : maNormalInterpolators.clear();
295 18747 : maTextureInterpolators.clear();
296 18747 : maInverseTextureInterpolators.clear();
297 18747 : }
298 :
299 : public:
300 13 : InterpolatorProvider3D() {}
301 :
302 68435 : ::std::vector< ip_triple >& getColorInterpolators() { return maColorInterpolators; }
303 0 : ::std::vector< ip_triple >& getNormalInterpolators() { return maNormalInterpolators; }
304 0 : ::std::vector< ip_double >& getTextureInterpolators() { return maTextureInterpolators; }
305 68435 : ::std::vector< ip_triple >& getInverseTextureInterpolators() { return maInverseTextureInterpolators; }
306 : };
307 : } // end of namespace basegfx
308 :
309 :
310 : // RasterConversionLineEntry3D for Rasterconversion of 3D PolyPolygons
311 :
312 : namespace basegfx
313 : {
314 : class RasterConversionLineEntry3D
315 : {
316 : private:
317 : ip_single maX;
318 : ip_single maZ;
319 : sal_Int32 mnY;
320 : sal_uInt32 mnCount;
321 :
322 : sal_uInt32 mnColorIndex;
323 : sal_uInt32 mnNormalIndex;
324 : sal_uInt32 mnTextureIndex;
325 : sal_uInt32 mnInverseTextureIndex;
326 :
327 : public:
328 29139 : RasterConversionLineEntry3D(const double& rfX, const double& rfDeltaX, const double& rfZ, const double& rfDeltaZ, sal_Int32 nY, sal_uInt32 nCount)
329 : : maX(rfX, rfDeltaX),
330 : maZ(rfZ, rfDeltaZ),
331 : mnY(nY),
332 : mnCount(nCount),
333 : mnColorIndex(SCANLINE_EMPTY_INDEX),
334 : mnNormalIndex(SCANLINE_EMPTY_INDEX),
335 : mnTextureIndex(SCANLINE_EMPTY_INDEX),
336 29139 : mnInverseTextureIndex(SCANLINE_EMPTY_INDEX)
337 29139 : {}
338 :
339 656 : void setColorIndex(sal_uInt32 nIndex) { mnColorIndex = nIndex; }
340 0 : void setNormalIndex(sal_uInt32 nIndex) { mnNormalIndex = nIndex; }
341 0 : void setTextureIndex(sal_uInt32 nIndex) { mnTextureIndex = nIndex; }
342 656 : void setInverseTextureIndex(sal_uInt32 nIndex) { mnInverseTextureIndex = nIndex; }
343 :
344 29789 : bool operator<(const RasterConversionLineEntry3D& rComp) const
345 : {
346 29789 : if(mnY == rComp.mnY)
347 : {
348 20601 : return maX.getVal() < rComp.maX.getVal();
349 : }
350 :
351 9188 : return mnY < rComp.mnY;
352 : }
353 :
354 352302 : bool decrementRasterConversionLineEntry3D(sal_uInt32 nStep)
355 : {
356 352302 : if(nStep >= mnCount)
357 : {
358 28692 : return false;
359 : }
360 : else
361 : {
362 323610 : mnCount -= nStep;
363 323610 : return true;
364 : }
365 : }
366 :
367 323610 : void incrementRasterConversionLineEntry3D(sal_uInt32 nStep, InterpolatorProvider3D& rProvider)
368 : {
369 323610 : const double fStep((double)nStep);
370 323610 : maX.increment(fStep);
371 323610 : maZ.increment(fStep);
372 323610 : mnY += nStep;
373 :
374 323610 : if(SCANLINE_EMPTY_INDEX != mnColorIndex)
375 : {
376 34219 : rProvider.getColorInterpolators()[mnColorIndex].increment(fStep);
377 : }
378 :
379 323610 : if(SCANLINE_EMPTY_INDEX != mnNormalIndex)
380 : {
381 0 : rProvider.getNormalInterpolators()[mnNormalIndex].increment(fStep);
382 : }
383 :
384 323610 : if(SCANLINE_EMPTY_INDEX != mnTextureIndex)
385 : {
386 0 : rProvider.getTextureInterpolators()[mnTextureIndex].increment(fStep);
387 : }
388 :
389 323610 : if(SCANLINE_EMPTY_INDEX != mnInverseTextureIndex)
390 : {
391 34219 : rProvider.getInverseTextureInterpolators()[mnInverseTextureIndex].increment(fStep);
392 : }
393 323610 : }
394 :
395 : // data read access
396 1407596 : const ip_single& getX() const { return maX; }
397 106706 : sal_Int32 getY() const { return mnY; }
398 236913 : const ip_single& getZ() const { return maZ; }
399 169263 : sal_uInt32 getColorIndex() const { return mnColorIndex; }
400 117939 : sal_uInt32 getNormalIndex() const { return mnNormalIndex; }
401 117939 : sal_uInt32 getTextureIndex() const { return mnTextureIndex; }
402 169263 : sal_uInt32 getInverseTextureIndex() const { return mnInverseTextureIndex; }
403 : };
404 : } // end of namespace basegfx
405 :
406 :
407 : // the basic RasterConverter itself. Only one method needs to be overridden. The
408 : // class itself is pure virtual
409 :
410 : namespace basegfx
411 : {
412 : class BASEGFX_DLLPUBLIC RasterConverter3D : public InterpolatorProvider3D
413 : {
414 : private:
415 : // the line entries for an area conversion run
416 : ::std::vector< RasterConversionLineEntry3D > maLineEntries;
417 :
418 : struct lineComparator
419 : {
420 350082 : bool operator()(const RasterConversionLineEntry3D* pA, const RasterConversionLineEntry3D* pB)
421 : {
422 : OSL_ENSURE(pA && pB, "lineComparator: empty pointer (!)");
423 350082 : return pA->getX().getVal() < pB->getX().getVal();
424 : }
425 : };
426 :
427 : void addArea(const B3DPolygon& rFill, const B3DHomMatrix* pViewToEye);
428 : void addArea(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye);
429 : void addEdge(const B3DPolygon& rFill, sal_uInt32 a, sal_uInt32 b, const B3DHomMatrix* pViewToEye);
430 :
431 : void rasterconvertB3DArea(sal_Int32 nStartLine, sal_Int32 nStopLine);
432 : void rasterconvertB3DEdge(const B3DPolygon& rLine, sal_uInt32 nA, sal_uInt32 nB, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth);
433 :
434 : virtual void processLineSpan(const RasterConversionLineEntry3D& rA, const RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount) = 0;
435 :
436 : public:
437 : RasterConverter3D();
438 : virtual ~RasterConverter3D();
439 :
440 : void rasterconvertB3DPolyPolygon(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye, sal_Int32 nStartLine, sal_Int32 nStopLine);
441 : void rasterconvertB3DPolygon(const B3DPolygon& rLine, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth);
442 : };
443 : } // end of namespace basegfx
444 :
445 : #endif // INCLUDED_BASEGFX_RASTER_RASTERCONVERT3D_HXX
446 :
447 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|