Mondschein Engine  0.3.0
bezierpatch.cpp
1 /* Mondschein Engine is a fast, powerful, and easy-to-use 3D realtime rendering engine.
2  *
3  * Copyright (C) 2009-2013 by Andreas Amereller
4  * E-Mail: andreas.amereller.dev@googlemail.com
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; either version 3 of the License, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include "core/bezierpatch.h"
22 #include "core/beziercurve.h"
23 #include "core/normgrid.h"
24 #include "core/mesh.h"
25 
26 using namespace mondschein;
27 using namespace math;
28 
29 Bezierpatch::Bezierpatch() : curves()
30 {
31  return;
32 }
33 
34 Bezierpatch::Bezierpatch(const std::vector<Beziercurve_p> &_c) : curves(_c)
35 {
36  return;
37 }
38 
39 Bezierpatch::Bezierpatch(Bezierpatch_c _b) : curves(_b->curves)
40 {
41  return;
42 }
43 
44 Bezierpatch::~Bezierpatch()
45 {
46  return;
47 }
48 
49 Bezierpatch &Bezierpatch::operator=(Bezierpatch_c _b)
50 {
51  curves=_b->curves;
52  return *this;
53 }
54 
55 Eigen::Vector3d Bezierpatch::operator()(float64 _t,float64 _u) const
56 {
57  try
58  {
59  return get_point(_t,_u);
60  }
61  catch (exception &e)
62  {
63  std::string err(*boost::get_error_info<exception_error>(e));
64  err+=", called in function\n\t";
65  err+="Eigen::Vector4d mondschein::math::Bezierpatch::operator()(float64 _t,float64 _u) const";
66  throw boost::enable_current_exception(e) << exception_error(err);
67  }
68 }
69 
70 void Bezierpatch::set_curves(const std::vector<Beziercurve_p> &_c)
71 {
72  curves=_c;
73  return;
74 }
75 
76 std::vector<Beziercurve_p> Bezierpatch::get_curves() const
77 {
78  return curves;
79 }
80 
82 {
83  return curves.size()-1;
84 }
85 
86 Eigen::Vector3d Bezierpatch::get_point(float64 _t,float64 _u) const
87 {
88  try
89  {
90  if (_u<0) _u=0;
91  else if (_u>1) _u=1;
92  std::vector<Eigen::Vector3d> v;
93  for (uint32 i=0; i<curves.size(); ++i)
94  {
95  v.push_back(curves.at(i)->get_point(_t));
96  }
97 
98  /* Application of the deCasteljau algorithm */
99  for (uint32 j=1; j<v.size(); ++j)
100  {
101  for (uint32 k=0; k<v.size()-j; ++k)
102  {
103  v.at(j)=(1-_u)*v.at(j)+_u*v.at(j+1);
104  }
105  }
106  return v.at(0);
107  }
108  catch (exception &e)
109  {
110  std::string err(*boost::get_error_info<exception_error>(e));
111  err+=", called in function\n\t";
112  err+="Eigen::Vector3d mondschein::math::Bezierpatch::get_point(float64 _t,float64 _u) const";
113  throw boost::enable_current_exception(e) << exception_error(err);
114  }
115  catch (std::exception &e)
116  {
117  std::string err("Mondschein Engine ERROR: ");
118  err+=e.what();
119  err+=", exception raised in function\n\t";
120  err+="Eigen::Vector3d mondschein::math::Bezierpatch::get_point(float64 _t,float64 _u) const";
121  throw boost::enable_current_exception(exception()) << exception_error(err);
122  }
123 }
124 
125 scene::Mesh_p Bezierpatch::generate_mesh(uint32 _n,uint32 _m, normal_calculation_e _normals) const
126 {
127  if ((_n<2) || (_m<2))
128  {
129  std::string err("Mondschein Engine ERROR: Cannot construct a square mesh out of ");
130  err+=_n; err+="x"; err+=_m;
131  err+=" vertices. Exception raised in function\n\t";
132  err+="mondschein::scene::Mesh_p mondschein::math::Bezierpatch::generate_mesh(uint32 _n,uint32 _m,";
133  err+="mondschein::math::normal_calculation_e _normals) const";
134  throw boost::enable_current_exception(exception()) << exception_error(err);
135  }
136  try
137  {
138  float64 n=1.0/_n;
139  float64 m=1.0/_m;
140  std::vector<std::vector<Eigen::Vector3d> > grid;
141  for (float64 t=0; t<=1; t+=n)
142  {
143  std::vector<Eigen::Vector3d> _grid;
144  for (float64 u=0; u<=1; u+=m)
145  {
146  _grid.push_back(get_point(t,u));
147  }
148  grid.push_back(_grid);
149  }
150  Normal_Grid_p ng(new Normal_Grid());
151  std::vector<Eigen::Vector3d> normals;
152  switch (_normals)
153  {
154  case FLAT:
155  normals=ng->flat(grid);
156  break;
157 
158  case FLAT_INV:
159  normals=ng->flat_inv(grid);
160  break;
161 
162  case INTERMEDIATE:
163  normals=ng->intermediate(grid);
164  break;
165 
166  case INTERMEDIATE_INV:
167  normals=ng->intermediate_inv(grid);
168  break;
169 
170  default:
171  std::string err("Mondschein Engine ERROR: Normal calculation type not supported. ");
172  err+="Exception raised in function\n\t";
173  err+="mondschein::scene::Mesh_p mondschein::math::Bezierpatch::generate_mesh(float64 _n,";
174  err+="float64 _m, mondschein::normal_calculation_e _normals) const";
175  throw boost::enable_current_exception(exception()) << exception_error(err);
176  break;
177  }
178  std::vector<Eigen::Vector4d> v;
179  std::vector<Eigen::Vector3d> vn;
180  std::vector<Eigen::Vector4d> vt;
181  std::vector<Eigen::Vector4d> vc;
182  Eigen::Vector4d tmp;
183  for (uint32 i=0; i<grid.size()-1; ++i)
184  {
185  for (uint32 j=0; j<grid.at(i).size()-1; ++i)
186  {
187  tmp << grid.at(i).at(j),1.0;
188  v.push_back(tmp);
189  tmp << grid.at(i+1).at(j),1.0;
190  v.push_back(tmp);
191  tmp << grid.at(i).at(j+1),1.0;
192  v.push_back(tmp);
193  if (_normals < INTERMEDIATE)
194  {
195  vn.push_back(normals.at(grid.at(i).size()*i+j*2));
196  vn.push_back(normals.at(grid.at(i).size()*i+j*2));
197  vn.push_back(normals.at(grid.at(i).size()*i+j*2));
198  }
199  else
200  {
201  vn.push_back(normals.at(grid.at(i).size()*(i)+j));
202  vn.push_back(normals.at(grid.at(i+1).size()*(i+1)+j));
203  vn.push_back(normals.at(grid.at(i).size()*(i)+j+1));
204  }
205  vt.push_back(Eigen::Vector4d(static_cast<float64>(i)/grid.size(),static_cast<float64>(j)/grid.at(i).size(),
206  0.0,1.0));
207  vt.push_back(Eigen::Vector4d(static_cast<float64>(i+1)/grid.size(),static_cast<float64>(j)/grid.at(i).size(),
208  0.0,1.0));
209  vt.push_back(Eigen::Vector4d(static_cast<float64>(i)/grid.size(),static_cast<float64>(j+1)/grid.at(i).size(),
210  0.0,1.0));
211  vc.push_back(Eigen::Vector4d(1.0,1.0,1.0,1.0));
212  vc.push_back(Eigen::Vector4d(1.0,1.0,1.0,1.0));
213  vc.push_back(Eigen::Vector4d(1.0,1.0,1.0,1.0));
214 
215  tmp << grid.at(i).at(j+1),1.0;
216  v.push_back(tmp);
217  tmp << grid.at(i+1).at(j),1.0;
218  v.push_back(tmp);
219  tmp << grid.at(i+1).at(j+1),1.0;
220  v.push_back(tmp);
221  if (_normals < INTERMEDIATE)
222  {
223  vn.push_back(normals.at(grid.at(i).size()*i+j*2+1));
224  vn.push_back(normals.at(grid.at(i).size()*i+j*2+1));
225  vn.push_back(normals.at(grid.at(i).size()*i+j*2+1));
226  }
227  else
228  {
229  vn.push_back(normals.at(grid.at(i).size()*(i)+j+1));
230  vn.push_back(normals.at(grid.at(i+1).size()*(i+1)+j));
231  vn.push_back(normals.at(grid.at(i+1).size()*(i+1)+j+1));
232  }
233  vt.push_back(Eigen::Vector4d(static_cast<float64>(i)/grid.size(),static_cast<float64>(j+1)/grid.at(i).size(),
234  0.0,1.0));
235  vt.push_back(Eigen::Vector4d(static_cast<float64>(i+1)/grid.size(),static_cast<float64>(j)/grid.at(i).size(),
236  0.0,1.0));
237  vt.push_back(Eigen::Vector4d(static_cast<float64>(i+1)/grid.size(),static_cast<float64>(j+1)/grid.at(i).size(),
238  0.0,1.0));
239  vc.push_back(Eigen::Vector4d(1.0,1.0,1.0,1.0));
240  vc.push_back(Eigen::Vector4d(1.0,1.0,1.0,1.0));
241  vc.push_back(Eigen::Vector4d(1.0,1.0,1.0,1.0));
242  }
243  }
244  return scene::Mesh_p(new scene::Mesh("BezierPatch",scene::mesh_attribs_t(v,vn,vt,vc)));
245  }
246  catch (exception &e)
247  {
248  std::string err(*boost::get_error_info<exception_error>(e));
249  err+=", called in function\n\t";
250  err+="mondschein::scene::Mesh_p mondschein::math::Bezierpatch::generate_mesh(float64 _t,float64 _u,";
251  err+="normal_calculation_e _normals) const";
252  throw boost::enable_current_exception(e) << exception_error(err);
253  }
254 }