Change Encyclo button name and macros icon
[ryzomcore.git] / nel / src / 3d / zone_smoother.cpp
blob6fd108ac78f001f729cf076bddfde88fc3b5b487
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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.
8 //
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/>.
17 #include "std3d.h"
19 #include "nel/3d/zone_smoother.h"
21 #ifdef DEBUG_NEW
22 #define new DEBUG_NEW
23 #endif
25 namespace NL3D
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();
37 dir0.normalize();
38 dir1.normalize();
39 // If not so colinear...
40 if(dir0*dir1<_CosThreshold)
41 return false;
43 // Then smooth.
44 if(_ContinuityC1)
46 tgtres= (int0+int1)/2;
48 else
50 // Make it colinear, but not at the middle.
51 // Respect the old distance ratio.
52 tgtres= (int0*norm1 + int1*norm0)/ (norm0+norm1);
56 return true;
60 // ***************************************************************************
61 void CZoneSmoother::smoothTangents(CZoneInfo zones[5], float angleThreshold, bool continuityC1)
63 sint i,j;
65 nlassert(zones[0].Patchs);
67 // Local info.
68 _CosThreshold= (float)cos(angleThreshold);
69 _ContinuityC1= continuityC1;
71 // 0. fill local Zone map.
72 //========================
73 _Zones.clear();
74 for(i=0;i<5;i++)
76 // If not NULL
77 if(zones[i].Patchs)
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];
90 // For all edges.
91 for(j=0;j<4;j++)
93 if (pat0.getSmoothFlag (i))
95 CPatchInfo::CBindInfo &bd= pat0.BindEdges[j];
96 // If normal bind (1/1), we can do the smooth.
97 if(bd.NPatchs==1)
99 // Retrieve the good neighbor zone.
100 TZoneInfoMap::iterator itZone= _Zones.find(bd.ZoneId);
101 // If zone here.
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.
107 CVector tgtRes;
108 sint edge0= j;
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.
114 // a. First tangent.
115 //==================
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.
125 //==================
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;
140 // End!!
144 } // NL3D