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_corner_smoother.h"
20 #include "nel/3d/patchuv_locator.h"
29 // ***************************************************************************
30 CZoneCornerSmoother::CZoneCornerSmoother()
35 // ***************************************************************************
36 void CZoneCornerSmoother::buildPatchBindInfo(CPatch
&pa
, const CZone::CPatchConnect
&pc
, bool smoothEdge
[4], bool cornerOnBind
[4])
41 Some terminology here: an edge is supposed going from Corner=edge, to corner=(edge+1)&3.
42 eg: edge 0 goes from corner0 to corner1.
45 for(corner
=0; corner
<4; corner
++)
46 cornerOnBind
[corner
]= false;
49 for(edge
=0; edge
<4; edge
++)
51 // Is this edge smoothed??
52 smoothEdge
[edge
]= pa
.getSmoothFlag(edge
);
55 CPatch::CBindInfo bindInfo
;
56 CPatchUVLocator patchUvLocator
;
57 pa
.getBindNeighbor(edge
, bindInfo
);
58 // if neighbor(s) is present.
61 patchUvLocator
.build(&pa
, edge
, bindInfo
);
62 // if not sameEdgeOnOrder (NB: all special cases of bind 1/X X/1 managed :) ), not smoothed!
63 if( !patchUvLocator
.sameEdgeOrder() )
64 smoothEdge
[edge
]= false;
66 // Manage bind 1/4 for the 2 patchs on the center of the bind.
67 if(bindInfo
.MultipleBindNum
==4 && (bindInfo
.MultipleBindId
==1 || bindInfo
.MultipleBindId
==2) )
69 // easy, this edge starts and ends on a bind...
70 cornerOnBind
[edge
]= true;
71 cornerOnBind
[(edge
+1)&3]= true;
73 // else for case bind 1/2, and for case of patch 0 and patch 3 of the bind 1/4.
74 else if(bindInfo
.MultipleBindNum
>=2)
76 // Beware of the mirroring!! (make a draw...)
78 ----------|-----------
90 ----------|-----------
92 // If we are the patch0 on the neighbor, then we start on a bind, else we ends.
93 if(bindInfo
.MultipleBindId
==0)
94 cornerOnBind
[edge
]= true;
96 cornerOnBind
[(edge
+1)&3]= true;
104 // ***************************************************************************
105 void CZoneCornerSmoother::updateVertex(uint idVert
, uint corner
, bool smoothEdge
[4], bool cornerOnBind
[4])
107 // get or insert into map (with default).
108 CVertexSmoothInfo
&vert
= VertexMap
[idVert
];
110 // inc the number of patch binded to this point.
113 // get the smooth flag of edge before and after this corner.
114 uint e0
= (4+corner
-1)&3;
116 // if any one of those edge is not smoothed, then this vertex is not smoothed.
117 if( !smoothEdge
[e0
] || !smoothEdge
[e1
] )
118 vert
.Smoothed
= false;
121 // Are we a vertex on a bind??
122 if(cornerOnBind
[corner
])
123 vert
.VertexOnBind
= true;
127 // ***************************************************************************
128 void CZoneCornerSmoother::computeAllCornerSmoothFlags(CZone
*zone
, std::vector
<CZone
*> neighborZones
)
131 sint npatchs
= zone
->getNumPatchs();
137 // for all patchs of the center zone, build the vertexMap.
139 for(i
=0; i
<npatchs
; i
++)
141 CPatch
&pa
= (CPatch
&)*(((const CZone
*)zone
)->getPatch(i
));
142 const CZone::CPatchConnect
&pc
= *(zone
->getPatchConnect(i
));
145 // build bind info for 4 edges and 4 vertices.
147 bool cornerOnBind
[4];
148 buildPatchBindInfo(pa
, pc
, smoothEdge
, cornerOnBind
);
151 for(corner
=0; corner
<4; corner
++)
153 // get the vertex id for this patch.
154 uint idVert
= pc
.BaseVertices
[corner
];
156 // update this vertex smooth info.
157 updateVertex(idVert
, corner
, smoothEdge
, cornerOnBind
);
159 // for Bind with neighbor zones, must insert it in the map CTessVertex* -> VertexId.
160 IdVertexMap
[pa
.getCornerVertex(corner
)]= idVert
;
165 // for all patchs of all neigbhors zone, update for vertices that are connected to the centerZone.
167 for(uint nbZone
=0; nbZone
<neighborZones
.size(); nbZone
++)
169 CZone
*neighborZone
= neighborZones
[nbZone
];
170 nlassert(neighborZone
);
171 for(i
=0; i
<neighborZone
->getNumPatchs(); i
++)
173 CPatch
&pa
= (CPatch
&)*(((const CZone
*)neighborZone
)->getPatch(i
));
174 const CZone::CPatchConnect
&pc
= *(neighborZone
->getPatchConnect(i
));
177 // build bind info for 4 edges and 4 vertices.
179 bool cornerOnBind
[4];
180 buildPatchBindInfo(pa
, pc
, smoothEdge
, cornerOnBind
);
183 for(corner
=0; corner
<4; corner
++)
185 // try to find the vertex of the centerZone binded to this corner.
186 ItIdVertexMap it
= IdVertexMap
.find(pa
.getCornerVertex(corner
));
188 // If this patch is binded on a vertex of the centerZone, must update this vertex.
189 if(it
!= IdVertexMap
.end())
191 // get the vertex id for this patch.
192 uint idVert
= it
->second
;
194 // update this vertex smooth info.
195 updateVertex(idVert
, corner
, smoothEdge
, cornerOnBind
);
203 // for all patchs of the center zone, build the finalSmooth.
205 for(i
=0; i
<npatchs
; i
++)
207 CPatch
&pa
= (CPatch
&)*(((const CZone
*)zone
)->getPatch(i
));
208 const CZone::CPatchConnect
&pc
= *(zone
->getPatchConnect(i
));
212 for(corner
=0; corner
<4; corner
++)
214 uint idVert
= pc
.BaseVertices
[corner
];
216 CVertexSmoothInfo
&vert
= VertexMap
[idVert
];
218 // the vertex is smoothed if all edges around him are smoothed, AND
219 // if it has 4 patchs around him or if it is a bind.
221 finalSmooth
= vert
.Smoothed
&& (vert
.VertexOnBind
|| vert
.NPatchShared
==4);
224 pa
.setCornerSmoothFlag(corner
, finalSmooth
);