Visualization Library 2.1.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
DoubleVertexRemover.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
33 #include <vlCore/Time.hpp>
34 
35 using namespace vl;
36 
37 namespace
38 {
39  class LessCompare
40  {
41  public:
42  LessCompare(const Geometry* geom)
43  {
44  for(int i=0; i<VA_MaxAttribCount; ++i)
45  if (geom->vertexAttribArray(i))
46  mAttribs.push_back(geom->vertexAttribArray(i));
47  }
48 
49  bool operator()(u32 a, u32 b) const
50  {
51  for(unsigned i=0; i<mAttribs.size(); ++i)
52  {
53  int val = mAttribs[i]->compare(a,b);
54  if (val != 0)
55  return val < 0;
56  }
57  return false;
58  }
59 
60  protected:
61  std::vector< const ArrayAbstract* > mAttribs;
62  };
63 
64  class EqualsCompare
65  {
66  public:
67  EqualsCompare(const Geometry* geom)
68  {
69  for(int i=0; i<VA_MaxAttribCount; ++i)
70  if (geom->vertexAttribArray(i))
71  mAttribs.push_back(geom->vertexAttribArray(i));
72  }
73 
74  bool operator()(u32 a, u32 b) const
75  {
76  for(unsigned i=0; i<mAttribs.size(); ++i)
77  {
78  if (mAttribs[i]->compare(a,b) != 0)
79  return false;
80  }
81  return true;
82  }
83 
84  protected:
85  std::vector< const ArrayAbstract* > mAttribs;
86  };
87 }
88 
89 //-----------------------------------------------------------------------------
90 template<class T>
91 ref<ArrayAbstract> VertexMapper::regenerateT(ArrayAbstract* data, const std::vector<u32>& map_new_to_old) const
92 {
93  ref<T> in_data = cast<T>(data);
94  if (in_data)
95  {
96  ref<T> out_data = new T;
97  out_data->resize(map_new_to_old.size());
98  for(unsigned i=0; i<map_new_to_old.size(); ++i) {
99  int j = map_new_to_old[i];
100  out_data->at(i) = in_data->at(j);
101  }
102  return out_data;
103  }
104  return NULL;
105 }
106 //-----------------------------------------------------------------------------
107 ref<ArrayAbstract> VertexMapper::regenerate(ArrayAbstract* data, const std::vector<u32>& map_new_to_old) const
108 {
109  ref<ArrayAbstract> out_data;
110 
111  if ( (out_data = regenerateT<ArrayInt4>(data, map_new_to_old)) )
112  return out_data;
113  else
114  if ( (out_data = regenerateT<ArrayInt3>(data, map_new_to_old)) )
115  return out_data;
116  else
117  if ( (out_data = regenerateT<ArrayInt2>(data, map_new_to_old)) )
118  return out_data;
119  else
120  if ( (out_data = regenerateT<ArrayUInt4>(data, map_new_to_old)) )
121  return out_data;
122  else
123  if ( (out_data = regenerateT<ArrayUInt3>(data, map_new_to_old)) )
124  return out_data;
125  else
126  if ( (out_data = regenerateT<ArrayUInt2>(data, map_new_to_old)) )
127  return out_data;
128  else
129  if ( (out_data = regenerateT<ArrayFloat4>(data, map_new_to_old)) )
130  return out_data;
131  else
132  if ( (out_data = regenerateT<ArrayFloat3>(data, map_new_to_old)) )
133  return out_data;
134  else
135  if ( (out_data = regenerateT<ArrayFloat2>(data, map_new_to_old)) )
136  return out_data;
137  else
138  if ( (out_data = regenerateT<ArrayDouble4>(data, map_new_to_old)) )
139  return out_data;
140  else
141  if ( (out_data = regenerateT<ArrayDouble3>(data, map_new_to_old)) )
142  return out_data;
143  else
144  if ( (out_data = regenerateT<ArrayDouble2>(data, map_new_to_old)) )
145  return out_data;
146  else
147  if ( (out_data = regenerateT<ArrayFloat1>(data, map_new_to_old)) )
148  return out_data;
149  else
150  if ( (out_data = regenerateT<ArrayDouble1>(data, map_new_to_old)) )
151  return out_data;
152  else
153  if ( (out_data = regenerateT<ArrayUInt1>(data, map_new_to_old)) )
154  return out_data;
155  else
156  if ( (out_data = regenerateT<ArrayInt1>(data, map_new_to_old)) )
157  return out_data;
158  else
159  if ( (out_data = regenerateT<ArrayByte1>(data, map_new_to_old)) )
160  return out_data;
161  else
162  if ( (out_data = regenerateT<ArrayShort1>(data, map_new_to_old)) )
163  return out_data;
164  else
165  if ( (out_data = regenerateT<ArrayUByte1>(data, map_new_to_old)) )
166  return out_data;
167  else
168  if ( (out_data = regenerateT<ArrayUShort1>(data, map_new_to_old)) )
169  return out_data;
170  else
171  if ( (out_data = regenerateT<ArrayUByte2>(data, map_new_to_old)) )
172  return out_data;
173  else
174  if ( (out_data = regenerateT<ArrayUByte3>(data, map_new_to_old)) )
175  return out_data;
176  else
177  if ( (out_data = regenerateT<ArrayUByte4>(data, map_new_to_old)) )
178  return out_data;
179  else
180  if ( (out_data = regenerateT<ArrayByte2>(data, map_new_to_old)) )
181  return out_data;
182  else
183  if ( (out_data = regenerateT<ArrayByte3>(data, map_new_to_old)) )
184  return out_data;
185  else
186  if ( (out_data = regenerateT<ArrayByte4>(data, map_new_to_old)) )
187  return out_data;
188  else
189  if ( (out_data = regenerateT<ArrayShort2>(data, map_new_to_old)) )
190  return out_data;
191  else
192  if ( (out_data = regenerateT<ArrayShort3>(data, map_new_to_old)) )
193  return out_data;
194  else
195  if ( (out_data = regenerateT<ArrayShort4>(data, map_new_to_old)) )
196  return out_data;
197  else
198  if ( (out_data = regenerateT<ArrayUShort2>(data, map_new_to_old)) )
199  return out_data;
200  else
201  if ( (out_data = regenerateT<ArrayUShort3>(data, map_new_to_old)) )
202  return out_data;
203  else
204  if ( (out_data = regenerateT<ArrayUShort4>(data, map_new_to_old)) )
205  return out_data;
206 
207  return NULL;
208 }
209 //-----------------------------------------------------------------------------
211 {
212  Time timer;
213  timer.start();
214 
215  mMapNewToOld.clear();
216  mMapOldToNew.clear();
217 
218  u32 vert_count = (u32)(geom->vertexArray() ? geom->vertexArray()->size() : 0);
219 
220  VL_CHECK(vert_count);
221  if (!vert_count)
222  return;
223 
224  std::vector<u32> verti;
225  verti.resize(vert_count);
226  mMapOldToNew.resize(vert_count);
227 
228  for(u32 i=0; i<verti.size(); ++i)
229  {
230  verti[i] = i;
231  mMapOldToNew[i] = 0xFFFFFFFF;
232  }
233 
234  std::sort(verti.begin(), verti.end(), LessCompare(geom));
235  EqualsCompare equal_vertex(geom);
236  mMapNewToOld.reserve(vert_count);
237  u32 unique_vert_idx = 0;
238  for(unsigned i=1; i<verti.size(); ++i)
239  {
240  if ( !equal_vertex(verti[unique_vert_idx], verti[i]) )
241  {
242  for(unsigned j=unique_vert_idx; j<i; ++j)
243  mMapOldToNew[verti[j]] = (u32)mMapNewToOld.size();
244  mMapNewToOld.push_back(verti[unique_vert_idx]);
245  unique_vert_idx = i;
246  }
247  }
248  for(unsigned j=unique_vert_idx; j<verti.size(); ++j)
249  {
250  mMapOldToNew[verti[j]] = (u32)mMapNewToOld.size();
251  mMapNewToOld.push_back(verti[unique_vert_idx]);
252  }
253 
254  // regenerate vertices
255 
256  geom->regenerateVertices(mMapNewToOld);
257 
258  // regenerate DrawCall
259 
260  std::vector< ref<DrawCall> > draw_cmd;
261  for(size_t idraw=0; idraw<geom->drawCalls().size(); ++idraw)
262  draw_cmd.push_back( geom->drawCalls().at(idraw) );
263  geom->drawCalls().clear();
264 
265  for(u32 idraw=0; idraw<draw_cmd.size(); ++idraw)
266  {
267  ref<DrawElementsUInt> de = new DrawElementsUInt( draw_cmd[idraw]->primitiveType() );
268  geom->drawCalls().push_back(de.get());
269  const u32 idx_count = draw_cmd[idraw]->countIndices();
270  de->indexBuffer()->resize(idx_count);
271  u32 i=0;
272  for(IndexIterator it = draw_cmd[idraw]->indexIterator(); it.hasNext(); it.next(), ++i)
273  de->indexBuffer()->at(i) = mMapOldToNew[it.index()];
274  }
275 
276  Log::debug( Say("DoubleVertexRemover : time=%.2ns, verts=%n/%n, saved=%n, ratio=%.2n\n") << timer.elapsed() << mMapNewToOld.size() << verti.size() << verti.size() - mMapNewToOld.size() << (float)mMapNewToOld.size()/verti.size() );
277 }
278 //-----------------------------------------------------------------------------
static void debug(const String &message)
Use this function to provide extra information useful to investigate and solve problems.
Definition: Log.cpp:145
The ArrayAbstract class defines an abstract interface to conveniently manipulate data stored in a Buf...
Definition: Array.hpp:58
void start(int index=0)
Definition: Time.hpp:76
real elapsed(int index=0) const
Definition: Time.hpp:82
const T * get() const
Definition: Object.hpp:128
A simple String formatting class.
Definition: Say.hpp:124
const ArrayAbstract * vertexArray() const
Conventional vertex array.
Definition: Geometry.hpp:248
void removeDoubles(Geometry *geom)
void resize(size_t dim)
Definition: Array.hpp:233
ref< ArrayAbstract > regenerate(ArrayAbstract *data, const std::vector< u32 > &map_new_to_old) const
Regenerates a new Array based on the given mapping.
The Geometry class is a Renderable that implements a polygonal mesh made of polygons, lines and points.
Definition: Geometry.hpp:66
Visualization Library main namespace.
Simple class to be used as a timer and to retrieve the current time and date.
Definition: Time.hpp:49
See DrawElements.
unsigned int u32
32 bits unsigned integer
Definition: std_types.hpp:51
const ArrayAbstract * vertexAttribArray(int attrib_location) const
Returns a generic vertex attribute&#39;s info.
Definition: Geometry.cpp:420
#define NULL
Definition: OpenGLDefs.hpp:81
arr_type * indexBuffer()
The BufferObject containing the indices used to render.
T_VectorType & at(size_t i)
Definition: Array.hpp:255
virtual size_t size() const =0
Returns the number of elements of an array.
void regenerateVertices(const std::vector< u32 > &map_new_to_old)
Regenerates the vertex position and attributes using the given new-to-old map.
Definition: Geometry.cpp:757
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
Wraps a IndexIteratorAbstract to iterate over the indices of a DrawCall.
#define VL_CHECK(expr)
Definition: checks.hpp:73
Collection< DrawCall > & drawCalls()
Returns the list of DrawCall objects bound to a Geometry.
Definition: Geometry.hpp:102