OGLplus (0.52.0) a C++ wrapper for OpenGL

cell.hpp
Go to the documentation of this file.
1 
12 #pragma once
13 #ifndef OGLPLUS_IMAGES_CELL_1107121519_HPP
14 #define OGLPLUS_IMAGES_CELL_1107121519_HPP
15 
16 #include <oglplus/images/image.hpp>
17 
18 #include <cassert>
19 #include <vector>
20 
21 namespace oglplus {
22 namespace images {
23 
24 template <typename T, unsigned CH>
25 class CellImageGen
26  : public Image
27 {
28 private:
29  static PixelDataFormat _fmt(unsigned c)
30  {
31  switch(c)
32  {
33  case 1: return PixelDataFormat::Red;
34  case 2: return PixelDataFormat::RG;
35  case 3: return PixelDataFormat::RGB;
36  case 4: return PixelDataFormat::RGBA;
37  default:;
38  }
39  assert(!"Invalid number of channels!");
40  return PixelDataFormat();
41  }
42 
43  template <typename X>
44  static PixelDataInternalFormat _ifmt(X*, unsigned c)
45  {
46  switch(c)
47  {
48  case 1: return PixelDataInternalFormat::Red;
49  case 2: return PixelDataInternalFormat::RG;
50  case 3: return PixelDataInternalFormat::RGB;
51  case 4: return PixelDataInternalFormat::RGBA;
52  default:;
53  }
54  assert(!"Invalid number of channels!");
55  return PixelDataInternalFormat();
56  }
57 public:
58  struct EulerDistance
59  {
60  GLdouble operator()(
61  std::size_t dims,
62  const Vec3d& tc,
63  const Vec3d& cc,
64  const Vec3d& co,
65  const Vec3d& is
66  ) const
67  {
68  GLdouble result = 0.0;
69  for(std::size_t d=0; d!=dims; ++d)
70  {
71  GLdouble dist = (tc[d]-(cc[d]+co[d]/is[d]))*is[d];
72  result += dist*dist;
73  }
74  return std::sqrt(result);
75  }
76  };
77 
78  template <typename GetDistance, typename GetValue>
79  CellImageGen(
80  GLsizei cell_w,
81  GLsizei cell_h,
82  GLsizei cell_d,
83  const Image& input,
84  GetDistance get_distance,
85  GetValue get_value
86  ): Image(
87  input.Width() *cell_w,
88  input.Height()*cell_h,
89  input.Depth() *cell_d,
90  CH, (T*)nullptr,
91  _fmt(CH), _ifmt((T*)nullptr, CH)
92  )
93  {
94  const T one = this->_one((T*)0);
95 
96  const GLdouble i_w = 1.0/Width();
97  const GLdouble i_h = 1.0/Height();
98  const GLdouble i_d = 1.0/Depth();
99 
100  const GLsizei iw = input.Width();
101  const GLsizei ih = input.Height();
102  const GLsizei id = input.Depth();
103 
104  std::size_t dims = 1;
105  if(ih*cell_h > 1) dims = 2;
106  if(id*cell_d > 1) dims = 3;
107 
108  const GLsizei kmin = (dims == 3)?-1:0;
109  const GLsizei kmax = (dims == 3)?+2:1;
110  const GLsizei jmin = (dims >= 2)?-1:0;
111  const GLsizei jmax = (dims >= 2)?+2:1;
112  const GLsizei imin = -1;
113  const GLsizei imax = +2;
114 
115  Vec3d colors[27];
116  GLdouble dists[27];
117 
118  const Vec3d is(iw, ih, id);
119 
120  auto pos = this->_begin<T>();
121 
122  for(GLsizei z=0; z!=Depth(); ++z)
123  {
124  GLsizei cz = z/cell_d;
125 
126  for(GLsizei y=0; y!=Height(); ++y)
127  {
128  GLsizei cy = y/cell_h;
129 
130  for(GLsizei x=0; x!=Width(); ++x)
131  {
132  GLsizei cx = x/cell_w;
133 
134  Vec3d tc = Vec3d(x*i_w, y*i_h, z*i_d);
135 
136  GLsizei l=0;
137 
138  for(GLsizei k=kmin; k<kmax; ++k)
139  for(GLsizei j=jmin; j<jmax; ++j)
140  for(GLsizei i=imin; i<imax; ++i)
141  {
142  GLsizei ccz = cz+k;
143  GLsizei ccy = cy+j;
144  GLsizei ccx = cx+i;
145 
146  Vec3d cc(
147  ccx*cell_w*i_w,
148  ccy*cell_h*i_h,
149  ccz*cell_d*i_d
150  );
151 
152  ccz = (ccz+id)%id;
153  ccy = (ccy+ih)%ih;
154  ccx = (ccx+iw)%iw;
155 
156  colors[l] = input.Pixel(ccx, ccy, ccz).xyz();
157  Vec3d co = colors[l];
158 
159  dists[l] = get_distance(dims, tc, cc, co, is);
160 
161  ++l;
162  }
163 
164  Vector<GLdouble, CH> value = get_value(dists, colors, l);
165 
166  for(std::size_t c=0; c!=CH; ++c)
167  {
168  assert(pos != this->_end<T>());
169  GLdouble vc = value.At(c);
170  *pos++ = T(one*vc);
171  }
172  }
173  }
174  }
175  assert(pos == this->_end<T>());
176  }
177 };
178 
179 class WorleyCellGen
180  : public CellImageGen<GLubyte, 1>
181 {
182 private:
183  typedef CellImageGen<GLubyte, 1> Base;
184 
185  template <typename ValueCalc>
186  struct DistanceValue
187  {
188  ValueCalc _calc_value;
189  const unsigned _order;
190  std::vector<GLdouble> _d;
191 
192  DistanceValue(ValueCalc calc_value, unsigned order)
193  : _calc_value(calc_value)
194  , _order(order)
195  , _d(order)
196  { }
197 
198  Vec1d operator()(
199  const GLdouble* dists,
200  const Vec3d*,
201  GLsizei count
202  )
203  {
204  for(unsigned o=0; o!=_order; ++o)
205  _d[o] = 2;
206 
207  for(GLsizei c=0; c<count; ++c)
208  {
209  for(unsigned o=0; o!=_order; ++o)
210  {
211  if(_d[o] > dists[c])
212  {
213  if(o+1 != _order)
214  {
215  _d[o+1] = _d[o];
216  }
217  _d[o] = dists[c];
218  break;
219  }
220  }
221  }
222  GLfloat result = _calc_value(_d);
223  if(result > 1) result = 1;
224  if(result < 0) result = 0;
225  return Vec1d(result);
226  }
227  };
228 public:
229  template <typename ValueCalc>
230  WorleyCellGen(
231  GLsizei cell_w,
232  GLsizei cell_h,
233  GLsizei cell_d,
234  const Image& input,
235  ValueCalc calc_value,
236  unsigned order
237  ): CellImageGen<GLubyte, 1>(
238  cell_w, cell_h, cell_d,
239  input,
240  Base::EulerDistance(),
241  DistanceValue<ValueCalc>(calc_value, order)
242  ){ }
243 };
244 
245 } // images
246 } // oglplus
247 
248 #endif // include guard
Vector< GLdouble, 1 > Vec1d
1D double-precision (degenerate) vector
Definition: vector.hpp:93
PixelDataInternalFormat
OpenGL pixel data internal format enumeration.
Definition: pixel_data.hpp:79
Vector< GLdouble, 3 > Vec3d
3D double-precision vector
Definition: vector.hpp:105
GLsizei Width(void) const
Returns the width of the image.
Definition: image.hpp:234
PixelDataFormat
OpenGL pixel data format enumeration.
Definition: pixel_data.hpp:50
GLsizei Height(void) const
Returns the height of the image.
Definition: image.hpp:240
Image data wrapper.

Copyright © 2010-2014 Matúš Chochlík, University of Žilina, Žilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Mon Sep 22 2014 by Doxygen (version 1.8.6).