1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "nel/3d/quad_effect.h"
30 // a 2d edge, ordered so that p1 is the highest point of the edge
33 CEdge(const NLMISC::CVector2f
&p1
, const NLMISC::CVector2f
&p2
)
47 NLMISC::CVector2f P1
, P2
;
50 // compares 2 edge, and take the highest
51 bool operator<(const CEdge
&e1
, const CEdge
&e2
) { return e1
.P1
.y
< e2
.P1
.y
; }
53 typedef std::deque
<CEdge
> TEdgeList
;
56 void CQuadEffect::makeRasters(const TPoint2DVect
&poly
57 , float quadWidth
, float quadHeight
58 , TRasters
&dest
, float &startY
65 sint size
= (sint
)poly
.size();
69 const float epsilon
= 10E-5f
;
70 uint aelSize
= 0; // size of active edge list
72 sint k
; // loop counter
74 static TEdgeList lel
, ael
; // the left edge list, and the active edge list
75 float highest
= poly
[0].y
;
79 /// build a segment list, and go through it;
81 for (k
= 0; k
< size
; ++k
)
85 CEdge(poly
[k
], poly
[k
== (size
- 1) ? 0 : k
+ 1])
87 if (poly
[k
].y
< highest
) { highest
= poly
[k
].y
; }
91 std::sort(lel
.begin(), lel
.end());
94 float left
= 0.f
, right
= 0.f
, inter
, diff
;
95 float currY
= highest
;
98 TEdgeList::iterator elIt
;
102 /// fetch new segment into the ael
104 && lel
.begin()->P1
.y
< (currY
+ quadHeight
)
107 ael
.push_front(lel
.front());
118 for (elIt
= ael
.begin(); elIt
!= ael
.end();)
120 if (elIt
->P2
.y
<= currY
)
122 // edge has gone out of active edge list
123 elIt
= ael
.erase(elIt
);
124 if (! --aelSize
) return;
130 /** edge is in scope. compute its extreme positions
131 * so we need to intersect it with the y = currY and y = currY + quadHeight lines
135 if (elIt
->P1
.y
>= currY
)
139 left
= right
= elIt
->P1
.x
;
144 left
= std::min(left
, elIt
->P1
.x
);
145 right
= std::max(right
, elIt
->P1
.x
);
150 // compute intersection
151 diff
= elIt
->P2
.y
- elIt
->P1
.y
;
154 inter
= elIt
->P1
.x
+ (elIt
->P2
.x
- elIt
->P1
.x
) * (currY
- elIt
->P1
.y
) / diff
;
163 left
= right
= inter
;
168 left
= std::min(left
, inter
);
169 right
= std::max(right
, inter
);
173 /// bottom of the edge
175 if (elIt
->P2
.y
<= currY
+ quadHeight
)
179 left
= right
= elIt
->P2
.x
;
184 left
= std::min(left
, elIt
->P2
.x
);
185 right
= std::max(right
, elIt
->P2
.x
);
190 // compute intersection
191 diff
= elIt
->P2
.y
- elIt
->P1
.y
;
194 inter
= elIt
->P1
.x
+ (elIt
->P2
.x
- elIt
->P1
.x
) * (currY
+ quadHeight
- elIt
->P1
.y
) / diff
;
203 left
= right
= inter
;
208 left
= std::min(left
, inter
);
209 right
= std::max(right
, inter
);
217 dest
.push_back(std::make_pair(left
, right
));
223 while (size
|| aelSize
);
228 void CQuadEffect::processPoly(const TPoint2DVect
&poly
229 , float quadWidth
, float quadHeight
233 static TRasters rDest
;
235 makeRasters(poly
, quadWidth
, quadHeight
, rDest
, currY
);
238 TRasters::const_iterator it
, endIt
= rDest
.end();
239 for (it
= rDest
.begin(); it
!= endIt
; ++it
)
241 const sint nbQuad
= (sint
) ceilf( (it
->second
- it
->first
) / quadWidth
);
242 float currX
= it
->first
;
243 for (sint k
= 0; k
< nbQuad
; ++k
)
245 dest
.push_back(NLMISC::CVector2f(currX
, currY
));