Field3D
FieldMapping.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------//
2 
3 /*
4  * Copyright (c) 2009 Sony Pictures Imageworks Inc
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution. Neither the name of Sony Pictures Imageworks nor the
18  * names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior written
20  * permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 //----------------------------------------------------------------------------//
37 
43 //----------------------------------------------------------------------------//
44 
45 #include <iostream>
46 #include <vector>
47 
48 #include "Field.h"
49 #include "FieldMapping.h"
50 #include "Types.h"
51 
52 #ifdef _MSC_VER
53 #define isnan(__x__) _isnan(__x__)
54 #endif
55 
56 //----------------------------------------------------------------------------//
57 
58 using namespace boost;
59 using namespace std;
60 
61 //----------------------------------------------------------------------------//
62 
64 
65 //----------------------------------------------------------------------------//
66 // Field3D namespaces
67 //----------------------------------------------------------------------------//
68 
69 
70 //----------------------------------------------------------------------------//
71 // Local namespace
72 //----------------------------------------------------------------------------//
73 
74 namespace {
75 
76  // Strings ---
77 
78  const string k_mappingName("FieldMapping");
79  const string k_nullMappingName("NullFieldMapping");
80  const string k_matrixMappingName("MatrixFieldMapping");
81  const string k_frustumMappingName("FrustumFieldMapping");
82 
83  // Functions ---
84 
85  template <class Matrix_T>
86  bool checkMatricesIdentical(const Matrix_T &m1, const Matrix_T &m2,
87  double tolerance)
88  {
89  if (m1.equalWithRelError(m2, tolerance)) {
90  return true;
91  }
92  V3d s1, r1, t1, sh1, s2, r2, t2, sh2;
93  if (!FIELD3D_EXTRACT_SHRT(m1, s1, sh1, r1, t1, false)) {
94  return false;
95  }
96  if (!FIELD3D_EXTRACT_SHRT(m2, s2, sh2, r2, t2, false)) {
97  return false;
98  }
99  if (!s1.equalWithRelError(s2, tolerance) ||
100  !r1.equalWithAbsError(r2, tolerance) ||
101  !t1.equalWithRelError(t2, tolerance)) {
102  return false;
103  }
104  return true;
105  }
106 
107 }
108 
109 //----------------------------------------------------------------------------//
110 // FieldMapping
111 //----------------------------------------------------------------------------//
112 
114  : RefBase(),
115  m_origin(V3i(0)),
116  m_res(V3i(1))
117 {
118  /* Empty */
119 }
120 
121 //----------------------------------------------------------------------------//
122 
124  : RefBase()
125 {
126  setExtents(extents);
127 }
128 
129 //----------------------------------------------------------------------------//
130 
132 {
133  /* Empty */
134 }
135 
136 //----------------------------------------------------------------------------//
137 
138 
139 std::string FieldMapping::className() const
140 {
141  return std::string(staticClassType());
142 }
143 
144 //----------------------------------------------------------------------------//
145 
146 void FieldMapping::setExtents(const Box3i &extents)
147 {
148  m_origin = extents.min;
149  m_res = extents.max - extents.min + V3i(1);
150  extentsChanged();
151 }
152 
153 //----------------------------------------------------------------------------//
154 
155 void FieldMapping::localToVoxel(const V3d &lsP, V3d &vsP) const
156 {
157  vsP = m_origin + lsP * m_res;
158 }
159 
160 //----------------------------------------------------------------------------//
161 
162 void FieldMapping::voxelToLocal(const V3d &vsP, V3d &lsP) const
163 {
164  lsP.x = FIELD3D_LERPFACTOR(vsP.x, m_origin.x, m_origin.x + m_res.x);
165  lsP.y = FIELD3D_LERPFACTOR(vsP.y, m_origin.y, m_origin.y + m_res.y);
166  lsP.z = FIELD3D_LERPFACTOR(vsP.z, m_origin.z, m_origin.z + m_res.z);
167 }
168 
169 //----------------------------------------------------------------------------//
170 // Utilities
171 //----------------------------------------------------------------------------//
172 
173 void worldToVoxel(const Field3D::FieldMapping* mapping,
174  const Box3d &wsBounds,
175  Box3d &vsBounds)
176 {
177  V3d test1, test2;
178  mapping->worldToVoxel(test1, test2);
180  V3d wsVerts[] = {
181  V3d(wsBounds.min.x, wsBounds.min.y, wsBounds.min.z),
182  V3d(wsBounds.max.x, wsBounds.min.y, wsBounds.min.z),
183  V3d(wsBounds.min.x, wsBounds.max.y, wsBounds.min.z),
184  V3d(wsBounds.max.x, wsBounds.max.y, wsBounds.min.z),
185  V3d(wsBounds.min.x, wsBounds.min.y, wsBounds.max.z),
186  V3d(wsBounds.max.x, wsBounds.min.y, wsBounds.max.z),
187  V3d(wsBounds.min.x, wsBounds.max.y, wsBounds.max.z),
188  V3d(wsBounds.max.x, wsBounds.max.y, wsBounds.max.z)
189  };
190  vsBounds.makeEmpty();
191  V3d vsP;
192  for (int i = 0; i < 8; i++) {
193  mapping->worldToVoxel(wsVerts[i], vsP);
194  vsBounds.extendBy(vsP);
195  }
196 }
197 
198 //----------------------------------------------------------------------------//
199 
200 void transformBounds(const M44d &mtx,
201  const Box3d &fromBounds,
202  Box3d &toBounds)
203 {
204  V3d verts[] = {
205  V3d(fromBounds.min.x, fromBounds.min.y, fromBounds.min.z),
206  V3d(fromBounds.max.x, fromBounds.min.y, fromBounds.min.z),
207  V3d(fromBounds.min.x, fromBounds.max.y, fromBounds.min.z),
208  V3d(fromBounds.max.x, fromBounds.max.y, fromBounds.min.z),
209  V3d(fromBounds.min.x, fromBounds.min.y, fromBounds.max.z),
210  V3d(fromBounds.max.x, fromBounds.min.y, fromBounds.max.z),
211  V3d(fromBounds.min.x, fromBounds.max.y, fromBounds.max.z),
212  V3d(fromBounds.max.x, fromBounds.max.y, fromBounds.max.z)
213  };
214  toBounds.makeEmpty();
215  V3d toP;
216  for (int i = 0; i < 8; i++) {
217  mtx.multVecMatrix(verts[i], toP);
218  toBounds.extendBy(toP);
219  }
220 }
221 
222 //----------------------------------------------------------------------------//
223 // NullFieldMapping
224 //----------------------------------------------------------------------------//
225 
226 std::string NullFieldMapping::className() const
227 {
228  return std::string(staticClassType());
229 }
230 
231 //----------------------------------------------------------------------------//
232 
234  double /* tolerance */) const
235 {
236  // For null mappings it's simple - if the other one is also a null mapping
237  // then true, otherwise it's false.
238 
239  return other->className() == k_nullMappingName;
240 }
241 
242 //----------------------------------------------------------------------------//
243 
245 {
246  return Ptr(new NullFieldMapping(*this));
247 }
248 
249 //----------------------------------------------------------------------------//
250 // MatrixFieldMapping
251 //----------------------------------------------------------------------------//
252 
254  : FieldMapping()
255 {
256  makeIdentity();
257 }
258 
259 //----------------------------------------------------------------------------//
260 
262  : FieldMapping(extents)
263 {
264  makeIdentity();
265 }
266 
267 //----------------------------------------------------------------------------//
268 
270 {
271  if (m_lsToWsCurve.numSamples() > 0) {
272  makeIdentity();
273  }
274  setLocalToWorld(0.0f, lsToWs);
275 }
276 
277 //----------------------------------------------------------------------------//
278 
279 void MatrixFieldMapping::setLocalToWorld(float t, const M44d &lsToWs)
280 {
281  m_lsToWsCurve.addSample(t, lsToWs);
282  updateTransform();
283 }
284 
285 //----------------------------------------------------------------------------//
286 
288 {
290  updateTransform();
291 }
292 
293 //----------------------------------------------------------------------------//
294 
296 {
297  updateTransform();
298 }
299 
300 //----------------------------------------------------------------------------//
301 
302 std::string MatrixFieldMapping::className() const
303 {
304  return std::string(staticClassType());
305 }
306 
307 //----------------------------------------------------------------------------//
308 
310  double tolerance) const
311 {
313 
314  if (other->className() != k_matrixMappingName) {
315  return false;
316  } else {
317 
319  FIELD_DYNAMIC_CAST<MatrixFieldMapping>(other);
320 
321  if (mm) {
322 
323  const SampleVec lsToWs1 = m_lsToWsCurve.samples();
324  const SampleVec lsToWs2 = mm->m_lsToWsCurve.samples();
325  const SampleVec vsToWs1 = m_vsToWsCurve.samples();
326  const SampleVec vsToWs2 = mm->m_vsToWsCurve.samples();
327 
328  size_t numSamples = lsToWs1.size();
329 
330  // First check if time sample counts differ
331  // lsToWs and vsToWs are guaranteed to have same sample count.
332  if (lsToWs1.size() != lsToWs2.size()) {
333  return false;
334  }
335 
336  // Then check if all time samples match, then check localToWorld
337  // and voxelToWorld matrices
338  for (size_t i = 0; i < numSamples; ++i) {
339  if (lsToWs1[i].first != lsToWs2[i].first) {
340  return false;
341  }
342  if (!checkMatricesIdentical(lsToWs1[i].second, lsToWs2[i].second,
343  tolerance)) {
344  return false;
345  }
346  if (!checkMatricesIdentical(vsToWs1[i].second, vsToWs2[i].second,
347  tolerance)) {
348  return false;
349  }
350  }
351 
352  return true;
353 
354  } else {
355  return false;
356  }
357  }
358  return false;
359 }
360 
361 //----------------------------------------------------------------------------//
362 
364 {
365  typedef MatrixCurve::SampleVec::const_iterator SampleIter;
366 
367  // Build the voxel to world space transforms ---
368  M44d lsToVs;
369  getLocalToVoxelMatrix(lsToVs);
370  M44d vsToLs = lsToVs.inverse();
371  // Loop over all samples in lsToWs, append vsToLs and create new curve
372  // Also handle the special case where lsToWs has no samples. In that
373  // case m_vsToWsCurve still has to have one sample.
374  const MatrixCurve::SampleVec &lsToWs = m_lsToWsCurve.samples();
376  for (SampleIter i = lsToWs.begin(), end = lsToWs.end(); i != end; i++) {
377  m_vsToWsCurve.addSample(i->first, vsToLs * i->second);
378  }
379 
380  // See if the curve has more than just a single sample
382 
383  // Sample the time-varying transforms at time=0.0
385  m_wsToLs = m_lsToWs.inverse();
386  m_vsToWs = vsToLs * m_lsToWs;
387  m_wsToVs = m_vsToWs.inverse();
388 
389  // Precompute the voxel size
390  V3d voxelOrigin, nextVoxel;
391  m_vsToWs.multVecMatrix(V3d(0, 0, 0), voxelOrigin);
392  m_vsToWs.multVecMatrix(V3d(1, 0, 0), nextVoxel);
393  m_wsVoxelSize.x = (nextVoxel - voxelOrigin).length();
394  m_vsToWs.multVecMatrix(V3d(0, 1, 0), nextVoxel);
395  m_wsVoxelSize.y = (nextVoxel - voxelOrigin).length();
396  m_vsToWs.multVecMatrix(V3d(0, 0, 1), nextVoxel);
397  m_wsVoxelSize.z = (nextVoxel - voxelOrigin).length();
398 }
399 
400 //----------------------------------------------------------------------------//
401 
403 {
404  // Local to voxel is a scale by the resolution of the field, offset
405  // to the origin of the extents
406  M44d scaling, translation;
407  scaling.setScale(m_res);
408  translation.setTranslation(m_origin);
409  result = scaling * translation;
410 }
411 
412 //----------------------------------------------------------------------------//
413 
415 {
416  return Ptr(new MatrixFieldMapping(*this));
417 }
418 
419 //----------------------------------------------------------------------------//
420 // FrustumFieldMapping
421 //----------------------------------------------------------------------------//
422 
424  : FieldMapping(),
425  m_zDistribution(PerspectiveDistribution),
426  m_defaultState(true)
427 {
428  reset();
429 }
430 
431 //----------------------------------------------------------------------------//
432 
434  : FieldMapping(extents)
435 {
436  reset();
437 }
438 
439 //----------------------------------------------------------------------------//
440 
441 void FrustumFieldMapping::setTransforms(const M44d &ssToWs, const M44d &csToWs)
442 {
443  setTransforms(0.0, ssToWs, csToWs);
444 }
445 
446 //----------------------------------------------------------------------------//
447 
449  const M44d &ssToWs, const M44d &csToWs)
450 {
451  if (m_defaultState) {
452  clearCurves();
453  m_defaultState = false;
454  }
455 
456  // Construct local-to-world transform from ssToWs
457  M44d lsToSs, scale, translation;
458  scale.setScale(V3d(2.0, 2.0, 1.0));
459  translation.setTranslation(V3d(-1.0, -1.0, 0.0));
460  lsToSs = scale * translation;
461  M44d lpsToWs = lsToSs * ssToWs;
462 
463  // Add samples to Curves
464  m_ssToWsCurve.addSample(t, ssToWs);
465  m_lpsToWsCurve.addSample(t, lpsToWs);
466  m_csToWsCurve.addSample(t, csToWs);
467 
468  // Compute near and far planes ---
469 
470  // Because the frustum may be skewed we can't just measure distance from
471  // the apex of the frustum to the world-space center point of the frustum.
472  // Instead, we transform into camera space and measure z depth there.
473 
474  V3d lsNearP(0.5, 0.5, 0.0), lsFarP(0.5, 0.5, 1.0);
475  V3d wsNearP, wsFarP, csNearP, csFarP;
476 
477  lpsToWs.multVecMatrix(lsNearP, wsNearP);
478  lpsToWs.multVecMatrix(lsFarP, wsFarP);
479 
480  M44d wsToCs = csToWs.inverse();
481  wsToCs.multVecMatrix(wsNearP, csNearP);
482  wsToCs.multVecMatrix(wsFarP, csFarP);
483 
484  double near = -csNearP.z;
485  double far = -csFarP.z;
486 
487  // Catch NaN here
488  if (std::isnan(near) || std::isnan(far)) {
489  throw BadPerspectiveMatrix("FrustumFieldMapping::setTransforms "
490  "received bad screen-to-world matrix");
491  }
492 
493  m_nearCurve.addSample(t, near);
494  m_farCurve.addSample(t, far);
495 
497 }
498 
499 //----------------------------------------------------------------------------//
500 
502 {
503  // Default camera to world ---
504 
505  M44d csToWs;
506  csToWs.makeIdentity();
507 
508  // Default screen to world ---
509 
510  double near = 1;
511  double far = 2;
512  double fovRadians = 45.0 * M_PI / 180.0;
513  double invTan = 1.0 / std::tan(fovRadians / 2.0);
514  double imageAspectRatio = 1.0;
515 
516  M44d perspective(1, 0, 0, 0,
517  0, 1, 0, 0,
518  0, 0, (far) / (far - near), 1,
519  0, 0, (- far * near) / (far - near), 0);
520 
521  M44d fov;
522  fov.setScale(V3d(invTan / imageAspectRatio, invTan, 1.0));
523 
524  M44d flipZ;
525  flipZ.setScale(V3d(1.0, 1.0, -1.0));
526 
527  M44d csToSs = flipZ * perspective * fov;
528 
529  M44d standardSsToWs = csToSs.inverse() * csToWs;
530 
531  // Set default state ---
532 
533  clearCurves();
534  setTransforms(standardSsToWs, csToWs);
535 
536  m_defaultState = true;
537 
539 }
540 
541 //----------------------------------------------------------------------------//
542 
544 {
546 }
547 
548 //----------------------------------------------------------------------------//
549 
550 void FrustumFieldMapping::worldToVoxel(const V3d &wsP, V3d &vsP) const
551 {
552  worldToVoxel(wsP, vsP, 0.0);
553 }
554 
555 //----------------------------------------------------------------------------//
556 
557 void FrustumFieldMapping::worldToVoxel(const V3d &wsP, V3d &vsP, float time) const
558 {
559  V3d lsP;
560  worldToLocal(wsP, lsP, time);
561  localToVoxel(lsP, vsP);
562 }
563 
564 //----------------------------------------------------------------------------//
565 
566 void FrustumFieldMapping::voxelToWorld(const V3d &vsP, V3d &wsP) const
567 {
568  voxelToWorld(vsP, wsP, 0.0);
569 }
570 
571 //----------------------------------------------------------------------------//
572 
573 void FrustumFieldMapping::voxelToWorld(const V3d &vsP, V3d &wsP, float time) const
574 {
575  V3d lsP;
576  voxelToLocal(vsP, lsP);
577  localToWorld(lsP, wsP, time);
578 }
579 
580 //----------------------------------------------------------------------------//
581 
582 void FrustumFieldMapping::worldToLocal(const V3d &wsP, V3d &lsP) const
583 {
584  worldToLocal(wsP, lsP, 0.0);
585 }
586 
587 //----------------------------------------------------------------------------//
588 
589 void FrustumFieldMapping::worldToLocal(const V3d &wsP, V3d &lsP, float time) const
590 {
591  switch (m_zDistribution) {
592  case UniformDistribution:
593  {
594  // First transform to local perspective space
595  V3d lpsP;
596  m_lpsToWsCurve.linear(time).inverse().multVecMatrix(wsP, lpsP);
597  // Also transform to camera space
598  V3d csP;
599  m_csToWsCurve.linear(time).inverse().multVecMatrix(wsP, csP);
600  // Interpolate near and far plane at current time
601  double near = m_nearCurve.linear(time);
602  double far = m_farCurve.linear(time);
603  // Use perspective-space X/Y and normalized depth for Z.
604  lsP = V3d(lpsP.x, lpsP.y, FIELD3D_LERPFACTOR(-csP.z, near, far));
605  break;
606  }
608  default:
609  {
610  m_lpsToWsCurve.linear(time).inverse().multVecMatrix(wsP, lsP);
611  break;
612  }
613  }
614 }
615 
616 //----------------------------------------------------------------------------//
617 
618 void FrustumFieldMapping::localToWorld(const V3d &lsP, V3d &wsP) const
619 {
620  localToWorld(lsP, wsP, 0.0);
621 }
622 
623 //----------------------------------------------------------------------------//
624 
625 void FrustumFieldMapping::localToWorld(const V3d &lsP, V3d &wsP, float time) const
626 {
627  switch (m_zDistribution) {
628  case UniformDistribution:
629  {
630  // Interpolate near and far plane at current time
631  double near = m_nearCurve.linear(time);
632  double far = m_farCurve.linear(time);
633  // In this case, local space is -not- equal to local perspective space
634  // Determine distance from camera
635  double wsDepthFromCam = FIELD3D_LERP(near, far, lsP.z);
636  // Transform point right in front of camera, X units away into world space
637  V3d lpsCenterP, wsCenterP, csCenterP(0.0, 0.0, -wsDepthFromCam);
638  m_csToWsCurve.linear(time).multVecMatrix(csCenterP, wsCenterP);
639  // Transform center point into screen space so we know what depth
640  // (in screen space) the voxel would live at -if- it were in local
641  // perspective space.
642  m_lpsToWsCurve.linear(time).inverse().multVecMatrix(wsCenterP, lpsCenterP);
643  // Now we create a local perspective coordinate that can be transformed
644  // using m_lpsToWsCurve
645  V3d lpsP(lsP.x, lsP.y, lpsCenterP.z);
646  // Now we can use m_lpsToWsCurve to transform the actual voxel location
647  m_lpsToWsCurve.linear(time).multVecMatrix(lpsP, wsP);
648  break;
649  }
651  default:
652  {
653  // In this case, local space and local perspective space are the same.
654  m_lpsToWsCurve.linear(time).multVecMatrix(lsP, wsP);
655  break;
656  }
657  }
658 }
659 
660 //----------------------------------------------------------------------------//
661 
663 {
664  return std::string(staticClassType());
665 }
666 
667 //----------------------------------------------------------------------------//
668 
670  double tolerance) const
671 {
673 
674  if (other->className() != k_frustumMappingName) {
675  return false;
676  } else {
677 
679  FIELD_DYNAMIC_CAST<FrustumFieldMapping>(other);
680 
681  if (fm) {
682 
683  const SampleVec lpsToWs1 = m_lpsToWsCurve.samples();
684  const SampleVec lpsToWs2 = fm->m_lpsToWsCurve.samples();
685  const SampleVec csToWs1 = m_csToWsCurve.samples();
686  const SampleVec csToWs2 = fm->m_csToWsCurve.samples();
687 
688  size_t numSamples = lpsToWs1.size();
689 
690  // Check that slice distributions match
691  if (m_zDistribution != fm->m_zDistribution) {
692  return false;
693  }
694 
695  // First check if time sample counts differ
696  // lpsToWs and csToWs are guaranteed to have same sample count.
697  if (lpsToWs1.size() != lpsToWs2.size()) {
698  return false;
699  }
700 
701  // Then check if all time samples match, then check localToWorld
702  // and voxelToWorld matrices
703  for (size_t i = 0; i < numSamples; ++i) {
704  if (lpsToWs1[i].first != lpsToWs2[i].first) {
705  return false;
706  }
707  if (!checkMatricesIdentical(lpsToWs1[i].second, lpsToWs2[i].second,
708  tolerance)) {
709  return false;
710  }
711  if (!checkMatricesIdentical(csToWs1[i].second, csToWs2[i].second,
712  tolerance)) {
713  return false;
714  }
715  }
716 
717  return true;
718 
719  } else {
720  return false;
721  }
722  }
723  return false;
724 }
725 
726 //----------------------------------------------------------------------------//
727 
728 V3d FrustumFieldMapping::wsVoxelSize(int /*i*/, int /*j*/, int k) const
729 {
730  k = std::min(std::max(k, static_cast<int>(m_origin.z)),
731  static_cast<int>(m_origin.z + m_res.z - 1));
732  return m_wsVoxelSize[k - static_cast<int>(m_origin.z)];
733 }
734 
735 //----------------------------------------------------------------------------//
736 
738 {
739  // Precompute the voxel size ---
740 
741  m_wsVoxelSize.resize(static_cast<int>(m_res.z),V3d(0.0));
742 
743  int i = static_cast<int>(m_origin.x + m_res.x / 2);
744  int j = static_cast<int>(m_origin.y + m_res.y / 2);
745 
746  // Do all z slices except last
747  int zMin = static_cast<int>(m_origin.z);
748  int zMax = static_cast<int>(m_origin.z + m_res.z - 1);
749 
750  for (int k = zMin, idx = 0; k < zMax; ++k, ++idx) {
751  V3d wsP, wsPx, wsPy, wsPz;
752  V3d vsP = discToCont(V3i(i, j, k));
753  V3d vsPx = discToCont(V3i(i + 1, j, k));
754  V3d vsPy = discToCont(V3i(i, j + 1, k));
755  V3d vsPz = discToCont(V3i(i, j, k + 1));
756  voxelToWorld(vsP, wsP);
757  voxelToWorld(vsPx, wsPx);
758  voxelToWorld(vsPy, wsPy);
759  voxelToWorld(vsPz, wsPz);
760  m_wsVoxelSize[idx] = V3d((wsPx - wsP).length(),
761  (wsPy - wsP).length(),
762  (wsPz - wsP).length());
763  }
764 
765  // Duplicate last value since there are no further slices to differentiate
766  // against
767  if (m_res.z >= 2) {
768  m_wsVoxelSize[static_cast<int>(m_res.z - 1)] = m_wsVoxelSize[static_cast<int>(m_res.z - 2)];
769  }
770 
771 }
772 
773 //----------------------------------------------------------------------------//
774 
776 {
777  // Local to voxel is a scale by the resolution of the field, offset
778  // to the origin of the extents
779  M44d scaling, translation;
780  scaling.setScale(m_res);
781  translation.setTranslation(m_origin);
782  result = scaling * translation;
783 }
784 
785 //----------------------------------------------------------------------------//
786 
788 {
791  m_nearCurve.clear();
792  m_farCurve.clear();
793 }
794 
795 //----------------------------------------------------------------------------//
796 
798 {
799  return Ptr(new FrustumFieldMapping(*this));
800 }
801 
802 //----------------------------------------------------------------------------//
803 
805 
806 //----------------------------------------------------------------------------//
FrustumFieldMapping::clearCurves
void clearCurves()
Clears all Curve data members. Used by setTransforms() to prepare for the first sample to be added.
Definition: FieldMapping.cpp:787
V3i
Imath::V3i V3i
Definition: SpiMathLib.h:71
FieldMapping::FieldMapping
FieldMapping()
Constructor.
Definition: FieldMapping.cpp:113
FrustumFieldMapping::voxelToWorld
virtual void voxelToWorld(const V3d &vsP, V3d &wsP) const
Transform from voxel space position into world space.
Definition: FieldMapping.cpp:566
MatrixFieldMapping::makeIdentity
void makeIdentity()
Sets the transform to identity. This makes it functionally equivalent to a NullFieldMapping.
Definition: FieldMapping.cpp:287
FieldMapping::extentsChanged
virtual void extentsChanged()
Implement this if the subclass needs to update itself when the resolution changes.
Definition: FieldMapping.h:161
FrustumFieldMapping::className
virtual std::string className() const
Returns the FieldMapping type name. Used when writing/reading from disk.
Definition: FieldMapping.cpp:662
MatrixFieldMapping::m_wsToLs
M44d m_wsToLs
World space to local space.
Definition: FieldMapping.h:506
V3d
Imath::V3d V3d
Definition: SpiMathLib.h:74
MatrixFieldMapping::clone
virtual FieldMapping::Ptr clone() const
Returns a pointer to a copy of the mapping, pure virtual so ensure derived classes properly implement...
Definition: FieldMapping.cpp:414
MatrixFieldMapping::setLocalToWorld
void setLocalToWorld(const M44d &lsToWs)
Sets the local to world transform. All other matrices will be updated based on this.
Definition: FieldMapping.cpp:269
FrustumFieldMapping::FrustumFieldMapping
FrustumFieldMapping()
Definition: FieldMapping.cpp:423
MatrixFieldMapping::className
virtual std::string className() const
Returns the FieldMapping type name. Used when writing/reading from disk.
Definition: FieldMapping.cpp:302
FIELD3D_NAMESPACE_OPEN::k_matrixMappingName
const string k_matrixMappingName("MatrixFieldMapping")
Types.h
Contains typedefs for the commonly used types in Field3D.
discToCont
double discToCont(int discCoord)
Goes from discrete coordinates to continuous coordinates See Graphics Gems - What is a pixel.
Definition: Field.h:1070
FieldMapping::m_res
V3d m_res
The integer voxel-space resolution of the underlying Field object. Is equal to field....
Definition: FieldMapping.h:193
NullFieldMapping::Ptr
boost::intrusive_ptr< NullFieldMapping > Ptr
Convenience typedef.
Definition: FieldMapping.h:243
MatrixFieldMapping::MatrixFieldMapping
MatrixFieldMapping()
Definition: FieldMapping.cpp:253
NullFieldMapping::staticClassType
static const char * staticClassType()
Definition: FieldMapping.h:250
FIELD3D_EXTRACT_SHRT
#define FIELD3D_EXTRACT_SHRT
Definition: SpiMathLib.h:93
FrustumFieldMapping::m_farCurve
FloatCurve m_farCurve
Time-varying far plane. Computed from m_lpsToWsCurve.
Definition: FieldMapping.h:730
FrustumFieldMapping::worldToLocal
virtual void worldToLocal(const V3d &wsP, V3d &lsP) const
Transform from world space position into local space.
Definition: FieldMapping.cpp:582
FieldMapping::Ptr
boost::intrusive_ptr< FieldMapping > Ptr
Definition: FieldMapping.h:92
MatrixFieldMapping::m_wsToVs
M44d m_wsToVs
World space to voxel space.
Definition: FieldMapping.h:512
Curve::numSamples
size_t numSamples() const
Returns the number of samples in the curve.
Definition: Curve.h:99
FrustumFieldMapping::setTransforms
void setTransforms(const M44d &ssToWs, const M44d &csToWs)
Sets the screenToWorld and cameraToWorld transforms. All other internal matrices will be updated base...
Definition: FieldMapping.cpp:441
FieldMapping.h
Contains the FieldMapping base class and the NullFieldMapping and MatrixFieldMapping subclasses.
FieldMapping::staticClassType
static const char * staticClassType()
Definition: FieldMapping.h:99
NullFieldMapping::className
virtual std::string className() const
Returns the FieldMapping type name. Used when writing/reading from disk.
Definition: FieldMapping.cpp:226
transformBounds
void transformBounds(const M44d &mtx, const Box3d &fromBounds, Box3d &toBounds)
Transforms a bounding box by a 4x4 matrix This is done by transforming each corner vertex from world ...
Definition: FieldMapping.cpp:200
FrustumFieldMapping::m_zDistribution
ZDistribution m_zDistribution
Slice distribution type.
Definition: FieldMapping.h:716
FieldMapping::className
virtual std::string className() const =0
Returns the FieldMapping type name. Used when writing/reading from disk.
Definition: FieldMapping.cpp:139
Curve::addSample
void addSample(const float t, const T &value)
Adds a sample point to the curve.
Definition: Curve.h:172
FieldMapping::voxelToLocal
void voxelToLocal(const V3d &vsP, V3d &lsP) const
Inverse of localToVoxel.
Definition: FieldMapping.cpp:162
FieldMapping::~FieldMapping
virtual ~FieldMapping()
Destructor.
Definition: FieldMapping.cpp:131
FIELD3D_NAMESPACE_OPEN::k_frustumMappingName
const string k_frustumMappingName("FrustumFieldMapping")
FieldMapping
Base class for mapping between world-, local- and voxel coordinates.
Definition: FieldMapping.h:87
FIELD3D_LERPFACTOR
#define FIELD3D_LERPFACTOR
Definition: SpiMathLib.h:92
FIELD3D_NAMESPACE_OPEN::k_mappingName
const string k_mappingName("FieldMapping")
MatrixFieldMapping::isIdentical
virtual bool isIdentical(FieldMapping::Ptr other, double tolerance=0.0) const
Whether the mapping is identical to another mapping.
Definition: FieldMapping.cpp:309
Curve::samples
const SampleVec & samples() const
Returns a const reference to the samples in the curve.
Definition: Curve.h:103
NullFieldMapping::NullFieldMapping
NullFieldMapping()
Definition: FieldMapping.h:260
FrustumFieldMapping::clone
virtual FieldMapping::Ptr clone() const
Returns a pointer to a copy of the mapping, pure virtual so ensure derived classes properly implement...
Definition: FieldMapping.cpp:797
FieldMapping::setExtents
void setExtents(const Box3i &extents)
This sets the field extents information to use for defining the local coordinate space.
Definition: FieldMapping.cpp:146
FrustumFieldMapping::Ptr
boost::intrusive_ptr< FrustumFieldMapping > Ptr
Convenience typedef.
Definition: FieldMapping.h:571
NullFieldMapping::isIdentical
virtual bool isIdentical(FieldMapping::Ptr other, double tolerance=0.0) const
Whether the mapping is identical to another mapping.
Definition: FieldMapping.cpp:233
FrustumFieldMapping::m_csToWsCurve
MatrixCurve m_csToWsCurve
Time-varying camera to world space transform.
Definition: FieldMapping.h:723
detail::max
T max(const T a, const T2 b)
Max operation on mixed types.
Definition: FieldSampler.h:32
MatrixFieldMapping::staticClassType
static const char * staticClassType()
Definition: FieldMapping.h:350
FieldMapping::m_origin
V3d m_origin
The integer voxel-space origin of the underlying Field object. Is equal to field.extents....
Definition: FieldMapping.h:190
MatrixFieldMapping::m_lsToWsCurve
MatrixCurve m_lsToWsCurve
Time-varying local to world space transform.
Definition: FieldMapping.h:515
FrustumFieldMapping::m_ssToWsCurve
MatrixCurve m_ssToWsCurve
Time-varying local perspective to world space transform This is not used in calculations,...
Definition: FieldMapping.h:721
MatrixFieldMapping::m_lsToWs
M44d m_lsToWs
Local space to world space.
Definition: FieldMapping.h:503
FIELD3D_NAMESPACE_OPEN::k_nullMappingName
const string k_nullMappingName("NullFieldMapping")
Box3d
Imath::Box3d Box3d
Definition: SpiMathLib.h:79
FrustumFieldMapping::UniformDistribution
@ UniformDistribution
Definition: FieldMapping.h:587
FrustumFieldMapping::getLocalToVoxelMatrix
void getLocalToVoxelMatrix(M44d &result)
Definition: FieldMapping.cpp:775
FrustumFieldMapping::m_lpsToWsCurve
MatrixCurve m_lpsToWsCurve
Time-varying local perspective to world space transform. Computed from m_ssToWsCurve.
Definition: FieldMapping.h:726
Field.h
Contains Field, WritableField and ResizableField classes.
FrustumFieldMapping::isIdentical
virtual bool isIdentical(FieldMapping::Ptr other, double tolerance=0.0) const
Whether the mapping is identical to another mapping.
Definition: FieldMapping.cpp:669
MatrixFieldMapping::m_wsVoxelSize
V3d m_wsVoxelSize
Precomputed world-space voxel size. Calculations may assume orthogonal transformation for efficiency.
Definition: FieldMapping.h:525
FIELD3D_NAMESPACE_SOURCE_CLOSE
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
Definition: ns.h:60
FrustumFieldMapping::m_defaultState
bool m_defaultState
Boolean to tell us if the mapping is in its 'default' state. This is needed because the class has a d...
Definition: FieldMapping.h:740
worldToVoxel
void worldToVoxel(const Field3D::FieldMapping *mapping, const Box3d &wsBounds, Box3d &vsBounds)
Computes a voxel space bounds given a bounding box in world space. This is done by transforming each ...
Definition: FieldMapping.cpp:173
M44d
Imath::M44d M44d
Definition: SpiMathLib.h:82
MatrixFieldMapping::m_vsToWs
M44d m_vsToWs
Voxel space to world space.
Definition: FieldMapping.h:509
FrustumFieldMapping::computeVoxelSize
void computeVoxelSize()
Updates the local to world transformation matrix.
Definition: FieldMapping.cpp:737
Curve< Imath::M44d >::SampleVec
std::vector< Sample > SampleVec
Definition: Curve.h:85
FIELD3D_LERP
#define FIELD3D_LERP
Definition: SpiMathLib.h:91
MatrixFieldMapping::updateTransform
void updateTransform()
Updates the local to world transformation matrix.
Definition: FieldMapping.cpp:363
MatrixFieldMapping::extentsChanged
virtual void extentsChanged()
Implement this if the subclass needs to update itself when the resolution changes.
Definition: FieldMapping.cpp:295
FrustumFieldMapping::reset
void reset()
Resets the transform. Makes a perspective transform at the origin, looking down the negative Z axis w...
Definition: FieldMapping.cpp:501
FIELD3D_NAMESPACE_OPEN
Definition: FieldMapping.cpp:74
FrustumFieldMapping::staticClassType
static const char * staticClassType()
Definition: FieldMapping.h:595
FrustumFieldMapping::extentsChanged
virtual void extentsChanged()
Implement this if the subclass needs to update itself when the resolution changes.
Definition: FieldMapping.cpp:543
Box3i
Imath::Box3i Box3i
Definition: SpiMathLib.h:77
FrustumFieldMapping::m_nearCurve
FloatCurve m_nearCurve
Time-varying near plane. Computed from m_lpsToWsCurve.
Definition: FieldMapping.h:728
MatrixFieldMapping::Ptr
boost::intrusive_ptr< MatrixFieldMapping > Ptr
Convenience typedef.
Definition: FieldMapping.h:341
MatrixFieldMapping::m_vsToWsCurve
MatrixCurve m_vsToWsCurve
Time-varying voxel to world space transform.
Definition: FieldMapping.h:517
RefBase
Definition: RefCount.h:107
FIELD3D_NAMESPACE_OPEN::checkMatricesIdentical
bool checkMatricesIdentical(const Matrix_T &m1, const Matrix_T &m2, double tolerance)
Definition: FieldMapping.cpp:86
FieldMapping::localToVoxel
void localToVoxel(const V3d &lsP, V3d &vsP) const
Transform from local space to voxel space. This is just a multiplication by the resolution of the Fie...
Definition: FieldMapping.cpp:155
NullFieldMapping::clone
virtual FieldMapping::Ptr clone() const
Returns a pointer to a copy of the mapping, pure virtual so ensure derived classes properly implement...
Definition: FieldMapping.cpp:244
FrustumFieldMapping::localToWorld
virtual void localToWorld(const V3d &lsP, V3d &wsP) const
Transform from local space position into world space.
Definition: FieldMapping.cpp:618
FrustumFieldMapping::worldToVoxel
virtual void worldToVoxel(const V3d &wsP, V3d &vsP) const
Transform from world space position into voxel space.
Definition: FieldMapping.cpp:550
detail::min
T min(const T a, const T2 b)
Min operation on mixed types.
Definition: FieldSampler.h:25
MatrixFieldMapping::getLocalToVoxelMatrix
void getLocalToVoxelMatrix(M44d &result)
Definition: FieldMapping.cpp:402
MatrixFieldMapping::m_isTimeVarying
bool m_isTimeVarying
Stores whether the curve has more than one time sample.
Definition: FieldMapping.h:521
FrustumFieldMapping::m_wsVoxelSize
std::vector< V3d > m_wsVoxelSize
Precomputed world-space voxel size. Calculations may assume orthogonal transformation for efficiency.
Definition: FieldMapping.h:734
FrustumFieldMapping::PerspectiveDistribution
@ PerspectiveDistribution
Definition: FieldMapping.h:586
Curve::clear
void clear()
Clears all samples in curve.
Definition: Curve.h:107
FrustumFieldMapping::wsVoxelSize
virtual V3d wsVoxelSize(int i, int j, int k) const
Returns world-space size of a voxel at the specified coordinate.
Definition: FieldMapping.cpp:728
Curve::linear
T linear(const float t) const
Linearly interpolates a value from the curve.
Definition: Curve.h:199