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/mrm_internal.h"
20 #include "nel/misc/common.h"
24 using namespace NLMISC
;
34 // ***************************************************************************
35 sint
CMRMSewingMesh::mustCollapseEdge(uint lod
, const CMRMEdge
&edge
, uint
&vertToCollapse
) const
37 nlassert(lod
<_Lods
.size());
38 for(uint i
=0;i
<_Lods
[lod
].EdgeToCollapse
.size();i
++)
40 if(edge
==_Lods
[lod
].EdgeToCollapse
[i
])
42 // the vertex which must be collapsed is v0.
43 vertToCollapse
= _Lods
[lod
].EdgeToCollapse
[i
].v0
;
52 // ***************************************************************************
53 sint
CMRMSewingMesh::getNumCollapseEdge(uint lod
) const
55 nlassert(lod
<_Lods
.size());
56 return (sint
)_Lods
[lod
].EdgeToCollapse
.size();
60 // ***************************************************************************
61 void CMRMSewingMesh::build(const CMesh::CInterface
&meshInt
, uint nWantedLods
, uint divisor
)
63 /* The polygon is MRM-egde-like reduced (pop an edge when needed)
64 At each lod we store what edge is collapsed.
67 _Lods
.resize(nWantedLods
);
70 std::vector
<CMRMEdge
> edgeList
;
71 uint nMaxEdges
= (uint
)meshInt
.Vertices
.size();
72 edgeList
.resize(nMaxEdges
);
73 for(uint i
=0;i
<nMaxEdges
;i
++)
76 edgeList
[i
].v1
= (i
+1)%nMaxEdges
;
79 // build how many edges the coarsest lod will have. At least 3 edge for a correct cross section
80 sint nBaseEdges
= nMaxEdges
/divisor
;
81 nBaseEdges
=max(nBaseEdges
,3);
83 // must fill all LODs, from end to start. do not proces last lod since it will be the coarsest mesh (no collapse)
84 for(uint lod
=nWantedLods
-1;lod
>0;lod
--)
87 sint nCurEdges
= (sint
)floor( 0.5f
+ nBaseEdges
+ (nMaxEdges
-nBaseEdges
) * (float)(lod
-1)/(nWantedLods
-1) );
88 nCurEdges
=max(nCurEdges
,3);
90 // the current edge list is reduced until same size as wanted
91 while(nCurEdges
<(sint
)edgeList
.size())
93 // search the smallest edge
94 float bestDist
= FLT_MAX
;
96 for(uint j
=0;j
<edgeList
.size();j
++)
98 uint precEdgeId
= (uint
)((j
+ edgeList
.size() -1) % edgeList
.size());
99 CVector edgeDelta
= (meshInt
.Vertices
[edgeList
[j
].v1
].Pos
- meshInt
.Vertices
[edgeList
[j
].v0
].Pos
);
101 // compute dist between 2 verts
102 float dist
= edgeDelta
.norm();
104 // compute dir of prec and cur edges
105 CVector curEdgeDir
= edgeDelta
;
106 CVector precEdgeDir
= (meshInt
.Vertices
[edgeList
[precEdgeId
].v1
].Pos
- meshInt
.Vertices
[edgeList
[precEdgeId
].v0
].Pos
);
107 curEdgeDir
.normalize();
108 precEdgeDir
.normalize();
110 // compute how linear they are from -1 to 1.
111 float angularPart
= curEdgeDir
* precEdgeDir
;
113 /* The more the edge is linear to the previous edge, the more we can collapse it.
114 If totaly linear (curEdgeDir*precEdgeDir==1), it should be a good idea to collapse it now.
115 But the fact is that this is an interface and we don't know what kind of mesh share those edges
116 (I mean it is possible that neighbors faces are absolutely not coplanar).
117 So don't add to much importance on Angular Part
119 const float angularBias
= 1; // if 0, 2 linear edges will collapse asap.
120 dist
*= angularBias
+ 1-angularPart
;
131 _Lods
[lod
].EdgeToCollapse
.push_back(edgeList
[bestEdgeId
]);
132 // changes vert ids of the prec edge. eg: edge(12) is deleted=> 01 12 23... becomes 02 23 (NB: 1 is collapsed to 2)
133 uint precEdgeId
= (uint
)((bestEdgeId
+edgeList
.size()-1)%edgeList
.size());
134 edgeList
[precEdgeId
].v1
= edgeList
[bestEdgeId
].v1
;
135 // and erase the edge from the current list
136 edgeList
.erase( edgeList
.begin()+bestEdgeId
);