3D Repo Bouncer  1.4
repo_node_utils.h
1 
22 #pragma once
23 #include <iostream>
24 #include <algorithm>
25 
26 #include <boost/functional/hash.hpp>
27 #include <boost/lexical_cast.hpp>
28 #include <boost/uuid/uuid.hpp>
29 #include <boost/uuid/uuid_generators.hpp>
30 #include <boost/uuid/uuid_io.hpp>
31 
32 #include <sstream>
33 
34 #include "../../lib/repo_log.h"
35 
36 //abstract out the use of boost inside the node codes
37 //incase we want to change it in the future
38 typedef boost::uuids::uuid repoUUID;
39 
41 {
42  std::size_t operator()(const repoUUID& uid) const
43  {
44  return boost::hash<boost::uuids::uuid>()(uid);
45  }
46 };
47 
48 typedef struct{
49  std::vector<float> ambient;
50  std::vector<float> diffuse;
51  std::vector<float> specular;
52  std::vector<float> emissive;
53  float opacity;
54  float shininess;
55  float shininessStrength;
56  bool isWireframe;
57  bool isTwoSided;
59 
60 typedef struct{
61  float r;
62  float g;
63  float b;
64  float a;
66 
67 typedef struct{
68  float x;
69  float y;
70  float z;
72 
73 typedef struct{
74  float x;
75  float y;
77 
78 typedef std::vector<uint32_t> repo_face_t;
79 
80 //This is used to map info for multipart optimization
81 typedef struct{
82  repo_vector_t min;
83  repo_vector_t max;
84  repoUUID mesh_id;
85  repoUUID material_id;
86  int32_t vertFrom;
87  int32_t vertTo;
88  int32_t triFrom;
89  int32_t triTo;
91 
92 static boost::uuids::random_generator gen;
93 
94 static repoUUID generateUUID(){
95  return gen();
96 }
97 
98 //FIXME: scope this
99 
112 static repoUUID stringToUUID(
113  const std::string &text,
114  const std::string &suffix = std::string())
115 {
116  boost::uuids::uuid uuid;
117  if (text.empty())
118  uuid = generateUUID();
119  else
120  {
121  try
122  {
123  boost::uuids::string_generator gen;
124  if (text.substr(0, 1) != "{")
125  uuid = gen("{" + text + "}");
126  else
127  uuid = gen(text);
128  }
129  catch (std::runtime_error e)
130  {
131  // uniformly distributed hash
132  boost::hash<std::string> string_hash;
133  std::string hashedUUID;
134  std::stringstream str;
135  str << string_hash(text);
136  str >> hashedUUID;
137 
138  // uuid: 8 + 4 + 4 + 4 + 12 = 32
139  // pad with zero, leave last places empty for suffix
140  while (hashedUUID.size() < 32 - suffix.size())
141  hashedUUID.append("0");
142  hashedUUID.append(suffix);
143  uuid = stringToUUID(hashedUUID, suffix);
144  }
145  }
146  return uuid;
147 }
148 
154 static std::string UUIDtoString(const repoUUID &id)
155 {
156  return boost::lexical_cast<std::string>(id);
157 }
158 
159 static std::string toString(const repo_face_t &f)
160 {
161  std::string str;
162  unsigned int mNumIndices = f.size();
163 
164  str += "[";
165  for (unsigned int i = 0; i < mNumIndices; i++)
166  {
167  str += std::to_string(f[i]);
168  if (i != mNumIndices - 1)
169  str += ", ";
170  }
171  str += "]";
172  return str;
173 }
174 
175 static std::string toString(const repo_color4d_t &color)
176 {
177  std::stringstream sstr;
178  sstr << "[" << color.r << ", " << color.g << ", " << color.b << ", " << color.a << "]";
179  return sstr.str();
180 }
181 
182 static std::string toString(const repo_vector_t &vec)
183 {
184  std::stringstream sstr;
185  sstr << "[" << vec.x << ", " << vec.y << ", " << vec.z << "]";
186  return sstr.str();
187 }
188 
189 static std::string toString(const repo_vector2d_t &vec)
190 {
191  std::stringstream sstr;
192  sstr << "[" << vec.x << ", " << vec.y << "]";
193  return sstr.str();
194 }
195 
204 template <class T>
205 static std::string vectorToString(const std::vector<T> &vec)
206 {
207  {
208  std::string str;
209  if (vec.size() > 0)
210  {
211  str += "[" + toString(vec.at(0));
212  if (vec.size() > 1)
213  str += ", ..., " + toString(vec.at(vec.size() - 1));
214  str += "]";
215  }
216  return str;
217  }
218 }
219 
220 static float dotProduct(const repo_vector_t a, const repo_vector_t b)
221 {
222  return a.x*b.x + a.y*b.y + a.z*b.z;
223 }
224 
225 static repo_vector_t crossProduct(const repo_vector_t &a, const repo_vector_t &b)
226 {
227  repo_vector_t product;
228  product.x = (a.y * b.z) - (a.z * b.y);
229  product.y = (a.z * b.x) - (a.x * b.z);
230  product.z = (a.x * b.y) - (a.y * b.x);
231 
232  return product;
233 }
234 
235 static std::string printMat(const std::vector<float> &mat)
236 {
237  std::stringstream ss;
238  for (int i = 0; i < mat.size(); ++i)
239  {
240  ss << " " << mat[i];
241  if (i % 4 == 3)
242  {
243  ss << "\n";
244  }
245  }
246 
247  return ss.str();
248 }
249 
250 static std::string printVec(const repo_vector_t &vec)
251 {
252  std::stringstream ss;
253  ss << "[ " << vec.x << ", " << vec.y << " ," << vec.z << " ]";
254 
255  return ss.str();
256 }
257 
265 static repo_vector_t multiplyMatVec(const std::vector<float> &mat, const repo_vector_t &vec)
266 {
267  repo_vector_t result;
268  if (mat.size() != 16)
269  {
270  repoError << "Trying to perform a matrix x vector multiplation with unexpected matrix size(" << mat.size() << ")";
271  }
272  else{
273  /*
274  00 01 02 03
275  04 05 06 07
276  08 09 10 11
277  12 13 14 15
278  */
279 
280  result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
281  result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
282  result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] * vec.z + mat[11];
283 
284  float sig = 1e-5;
285 
286  if (fabs(mat[12]) > sig || fabs(mat[13]) > sig || fabs(mat[14]) > sig || fabs(mat[15] - 1) > sig)
287  {
288  repoWarning << "Potentially incorrect transformation : does not expect the last row to have values!";
289  }
290  }
291 
292  return result;
293 }
294 
303 static repo_vector_t multiplyMatVecFake3x3(const std::vector<float> &mat, const repo_vector_t &vec)
304 {
305  repo_vector_t result;
306  if (mat.size() != 16)
307  {
308  repoError << "Trying to perform a matrix x vector multiplation with unexpected matrix size(" << mat.size() << ")";
309  }
310  else{
311  /*
312  00 01 02 03
313  04 05 06 07
314  08 09 10 11
315  12 13 14 15
316  */
317 
318  result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z;
319  result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z;
320  result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] * vec.z;
321  }
322 
323  return result;
324 }
325 
326 static float calculateDeterminant(std::vector<float> mat)
327 {
328  /*
329  00 01 02 03
330  04 05 06 07
331  08 09 10 11
332  12 13 14 15
333  */
334 
335  float a1 = mat[0], a2 = mat[1], a3 = mat[2], a4 = mat[3];
336  float b1 = mat[4], b2 = mat[5], b3 = mat[6], b4 = mat[7];
337  float c1 = mat[8], c2 = mat[9], c3 = mat[10], c4 = mat[11];
338  float d1 = mat[12], d2 = mat[13], d3 = mat[14], d4 = mat[15];
339 
340  float a1b2 = (a1 * b2) *(c3 * d4 - c4 * d3);
341  float a1b3 = (a1 * b3) *(c4 * d2 - c2 * d4);
342  float a1b4 = (a1 * b4) *(c2 * d3 - c3 * d2);
343 
344  float a2b1 = -(a2 * b1) *(c3 * d4 - c4 * d3);
345  float a2b3 = -(a2 * b3) *(c4 * d1 - c1 * d4);
346  float a2b4 = -(a2 * b4) *(c1 * d3 - c3 * d1);
347 
348  float a3b1 = (a3 * b1) *(c2 * d4 - c4 * d2);
349  float a3b2 = (a3 * b2) *(c4 * d1 - c1 * d4);
350  float a3b4 = (a3 * b4) *(c1 * d2 - c2 * d1);
351 
352  float a4b1 = -(a4 * b1) *(c2 * d3 - c3 * d2);
353  float a4b2 = -(a4 * b2) *(c3 * d1 - c1 * d3);
354  float a4b3 = -(a4 * b3) *(c1 * d2 - c2 * d1);
355 
356  return a1b2 + a1b3 + a1b4
357  + a2b1 + a2b3 + a2b4
358  + a3b1 + a3b2 + a3b4
359  + a4b1 + a4b2 + a4b3;
360 }
361 
362 static std::vector<float> invertMat(const std::vector<float> &mat)
363 {
364  std::vector<float> result;
365  result.resize(16);
366 
367  if (mat.size() != 16)
368  {
369  repoError << "Unsupported vector size (" << mat.size() << ")!";
370  }
371  else
372  {
373  const float det = calculateDeterminant(mat);
374  if (det == 0)
375  {
376  repoError << "Trying to invert a matrix with determinant = 0!";
377  }
378  else
379  {
380  const float inv_det = 1. / det;
381 
382  float a1 = mat[0], a2 = mat[1], a3 = mat[2], a4 = mat[3];
383  float b1 = mat[4], b2 = mat[5], b3 = mat[6], b4 = mat[7];
384  float c1 = mat[8], c2 = mat[9], c3 = mat[10], c4 = mat[11];
385  float d1 = mat[12], d2 = mat[13], d3 = mat[14], d4 = mat[15];
386 
387  result[0] = inv_det * (b2 * (c3 * d4 - c4 * d3) + b3 * (c4 * d2 - c2 * d4) + b4 * (c2 * d3 - c3 * d2));
388  result[1] = -inv_det * (a2 * (c3 * d4 - c4 * d3) + a3 * (c4 * d2 - c2 * d4) + a4 * (c2 * d3 - c3 * d2));
389  result[2] = inv_det * (a2 * (b3 * d4 - b4 * d3) + a3 * (b4 * d2 - b2 * d4) + a4 * (b2 * d3 - b3 * d2));
390  result[3] = -inv_det * (a2 * (b3 * c4 - b4 * c3) + a3 * (b4 * c2 - b2 * c4) + a4 * (b2 * c3 - b3 * c2));
391 
392  result[4] = -inv_det * (b1 * (c3 * d4 - c4 * d3) + b3 * (c4 * d1 - c1 * d4) + b4 * (c1 * d3 - c3 * d1));
393  result[5] = inv_det * (a1 * (c3 * d4 - c4 * d3) + a3 * (c4 * d1 - c1 * d4) + a4 * (c1 * d3 - c3 * d1));
394  result[6] = -inv_det * (a1 * (b3 * d4 - b4 * d3) + a3 * (b4 * d1 - b1 * d4) + a4 * (b1 * d3 - b3 * d1));
395  result[7] = inv_det * (a1 * (b3 * c4 - b4 * c3) + a3 * (b4 * c1 - b1 * c4) + a4 * (b1 * c3 - b3 * c1));
396 
397  result[8] = inv_det * (b1 * (c2 * d4 - c4 * d2) + b2 * (c4 * d1 - c1 * d4) + b4 * (c1 * d2 - c2 * d1));
398  result[9] = -inv_det * (a1 * (c2 * d4 - c4 * d2) + a2 * (c4 * d1 - c1 * d4) + a4 * (c1 * d2 - c2 * d1));
399  result[10] = inv_det * (a1 * (b2 * d4 - b4 * d2) + a2 * (b4 * d1 - b1 * d4) + a4 * (b1 * d2 - b2 * d1));
400  result[11] = -inv_det * (a1 * (b2 * c4 - b4 * c2) + a2 * (b4 * c1 - b1 * c4) + a4 * (b1 * c2 - b2 * c1));
401 
402  result[12] = -inv_det * (b1 * (c2 * d3 - c3 * d2) + b2 * (c3 * d1 - c1 * d3) + b3 * (c1 * d2 - c2 * d1));
403  result[13] = inv_det * (a1 * (c2 * d3 - c3 * d2) + a2 * (c3 * d1 - c1 * d3) + a3 * (c1 * d2 - c2 * d1));
404  result[14] = -inv_det * (a1 * (b2 * d3 - b3 * d2) + a2 * (b3 * d1 - b1 * d3) + a3 * (b1 * d2 - b2 * d1));
405  result[15] = inv_det * (a1 * (b2 * c3 - b3 * c2) + a2 * (b3 * c1 - b1 * c3) + a3 * (b1 * c2 - b2 * c1));
406  }
407  }
408 
409  return result;
410 }
411 
412 static std::vector<float> matMult(const std::vector<float> &mat1, const std::vector<float> &mat2)
413 {
414  std::vector<float> result;
415  if (mat1.size() != mat2.size() != 16)
416  {
417  result.resize(16);
418 
419  for (int i = 0; i < 4; ++i)
420  {
421  for (int j = 0; j < 4; ++j)
422  {
423  size_t resultIdx = i * 4 + j;
424  result[resultIdx] = 0;
425  for (int k = 0; k < 4; ++k)
426  {
427  result[resultIdx] += mat1[i * 4 + k] * mat2[k * 4 + j];
428  }
429  }
430  }
431  }
432  else
433  {
434  repoError << "We currently only support 4x4 matrix multiplications";
435  }
436 
437  return result;
438 }
439 
440 static std::vector<float> transposeMat(const std::vector<float> &mat)
441 {
442  std::vector<float> result(mat.begin(), mat.end());
443 
444  if (mat.size() != 16)
445  {
446  repoError << "Unsupported vector size (" << mat.size() << ")!";
447  }
448  else
449  {
450  /*
451  00 01 02 03 00 04 08 12
452  04 05 06 07 -----> 01 05 09 13
453  08 09 10 11 02 06 10 14
454  12 13 14 15 03 07 11 15
455  */
456 
457  result[1] = mat[4];
458  result[4] = mat[1];
459  result[2] = mat[8];
460  result[8] = mat[2];
461  result[3] = mat[12];
462  result[12] = mat[3];
463  result[6] = mat[9];
464  result[9] = mat[6];
465  result[7] = mat[13];
466  result[13] = mat[7];
467  result[11] = mat[14];
468  result[14] = mat[11];
469  }
470 
471  return result;
472 }
473 
474 static void normalize(repo_vector_t &a)
475 {
476  float length = std::sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
477 
478  if (length > 0)
479  {
480  a.x /= length;
481  a.y /= length;
482  a.z /= length;
483  }
484 }
485 
486 static bool nameCheck(const char &c)
487 {
488  return c == ' ' || c == '$' || c == '.';
489 }
490 
491 static bool dbNameCheck(const char &c)
492 {
493  return c == '/' || c == '\\' || c == '.' || c == ' '
494  || c == '\"' || c == '$' || c == '*' || c == '<'
495  || c == '>' || c == ':' || c == '?';
496 }
497 
498 static bool extNameCheck(const char &c)
499 {
500  return c == ' ' || c == '$';
501 }
502 
503 static std::string sanitizeExt(const std::string& name)
504 {
505  // http://docs.mongodb.org/manual/reference/limits/#Restriction-on-Collection-Names
506  std::string newName(name);
507  std::replace_if(newName.begin(), newName.end(), extNameCheck, '_');
508  auto strPos = newName.find("system.");
509  if (strPos != std::string::npos)
510  {
511  newName.replace(strPos, sizeof("system."), "");
512  }
513  return newName;
514 }
515 
516 static std::string sanitizeName(const std::string& name)
517 {
518  // http://docs.mongodb.org/manual/reference/limits/#Restriction-on-Collection-Names
519  std::string newName(name);
520  std::replace_if(newName.begin(), newName.end(), nameCheck, '_');
521  auto strPos = newName.find("system.");
522  if (strPos != std::string::npos)
523  {
524  newName.replace(strPos, sizeof("system."), "");
525  }
526  return newName;
527 }
528 
529 static std::string sanitizeDatabaseName(const std::string& name)
530 {
531  // http://docs.mongodb.org/manual/reference/limits/#naming-restrictions
532 
533  // Cannot contain any of /\. "$*<>:|?
534  std::string newName(name);
535  std::replace_if(newName.begin(), newName.end(), dbNameCheck, '_');
536  auto strPos = newName.find("system.");
537  if (strPos != std::string::npos)
538  {
539  newName.replace(strPos, sizeof("system."), "");
540  }
541  return newName;
542 }
Definition: repo_node_utils.h:60
Definition: repo_node_utils.h:73
Definition: repo_node_utils.h:67
Definition: repo_node_utils.h:81
Definition: repo_node_utils.h:40
Definition: repo_node_utils.h:48