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/zone_smoother.h"
29 // ***************************************************************************
30 bool CZoneSmoother::smoothTangent(const CVector
&tgt
, const CVector
&int0
, const CVector
&int1
, CVector
&tgtres
)
32 // First, test anglethreshold.
33 CVector dir0
= tgt
-int0
;
34 CVector dir1
= int1
-tgt
;
35 float norm0
= dir0
.norm();
36 float norm1
= dir1
.norm();
39 // If not so colinear...
40 if(dir0
*dir1
<_CosThreshold
)
46 tgtres
= (int0
+int1
)/2;
50 // Make it colinear, but not at the middle.
51 // Respect the old distance ratio.
52 tgtres
= (int0
*norm1
+ int1
*norm0
)/ (norm0
+norm1
);
60 // ***************************************************************************
61 void CZoneSmoother::smoothTangents(CZoneInfo zones
[5], float angleThreshold
, bool continuityC1
)
65 nlassert(zones
[0].Patchs
);
68 _CosThreshold
= (float)cos(angleThreshold
);
69 _ContinuityC1
= continuityC1
;
71 // 0. fill local Zone map.
72 //========================
79 _Zones
.insert( TZoneInfoMap::value_type(zones
[i
].ZoneId
, zones
[i
]) );
83 // 1. Fot all patchs of zones[0].
84 //===============================
85 std::vector
<CPatchInfo
> &patchs
= *(zones
[0].Patchs
);
86 for(i
=0;i
<(sint
)patchs
.size();i
++)
88 CPatchInfo
&pat0
= patchs
[i
];
93 if (pat0
.getSmoothFlag (i
))
95 CPatchInfo::CBindInfo
&bd
= pat0
.BindEdges
[j
];
96 // If normal bind (1/1), we can do the smooth.
99 // Retrieve the good neighbor zone.
100 TZoneInfoMap::iterator itZone
= _Zones
.find(bd
.ZoneId
);
102 if(itZone
!=_Zones
.end())
104 CZoneInfo
&zi
= itZone
->second
;
105 CPatchInfo
&pat1
= (*zi
.Patchs
)[bd
.Next
[0]];
106 // Here, we have the 2 patchs, and we must smooth 2 tangents.
109 sint edge1
= bd
.Edge
[0];
111 // Make a draw to understand (see Bezier patchs conventions).
112 // The key is: Patchs are always CCW, so must smooth the patchs one front of the other.
116 if(smoothTangent(pat0
.Patch
.Tangents
[edge0
*2], pat0
.Patch
.Interiors
[edge0
],
117 pat1
.Patch
.Interiors
[(edge1
+1)%4], tgtRes
))
119 // Set the result on the 2 patchs.
120 pat0
.Patch
.Tangents
[edge0
*2]= tgtRes
;
121 pat1
.Patch
.Tangents
[edge1
*2+1]= tgtRes
;
124 // b. Second tangent.
126 if(smoothTangent(pat0
.Patch
.Tangents
[edge0
*2+1], pat0
.Patch
.Interiors
[(edge0
+1)%4],
127 pat1
.Patch
.Interiors
[edge1
], tgtRes
))
129 // Set the result on the 2 patchs.
130 pat0
.Patch
.Tangents
[edge0
*2+1]= tgtRes
;
131 pat1
.Patch
.Tangents
[edge1
*2]= tgtRes
;