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 WIN32
53#define isnan(__x__) _isnan(__x__)
54#endif
55
56//----------------------------------------------------------------------------//
57
58using namespace boost;
59using namespace std;
60
61//----------------------------------------------------------------------------//
62
64
65//----------------------------------------------------------------------------//
66// Field3D namespaces
67//----------------------------------------------------------------------------//
68
69
70//----------------------------------------------------------------------------//
71// Local namespace
72//----------------------------------------------------------------------------//
73
74namespace {
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
139std::string FieldMapping::className() const
140{
141 return std::string(staticClassType());
142}
143
144//----------------------------------------------------------------------------//
145
146void FieldMapping::setExtents(const Box3i &extents)
147{
148 m_origin = extents.min;
149 m_res = extents.max - extents.min + V3i(1);
151}
152
153//----------------------------------------------------------------------------//
154
155void FieldMapping::localToVoxel(const V3d &lsP, V3d &vsP) const
156{
157 vsP = m_origin + lsP * m_res;
158}
159
160//----------------------------------------------------------------------------//
161
162void 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
173void 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
200void 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
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
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
279void MatrixFieldMapping::setLocalToWorld(float t, const M44d &lsToWs)
280{
281 m_lsToWsCurve.addSample(t, lsToWs);
283}
284
285//----------------------------------------------------------------------------//
286
292
293//----------------------------------------------------------------------------//
294
299
300//----------------------------------------------------------------------------//
301
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
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.
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
441void 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
547
548//----------------------------------------------------------------------------//
549
550void FrustumFieldMapping::worldToVoxel(const V3d &wsP, V3d &vsP) const
551{
552 worldToVoxel(wsP, vsP, 0.0);
553}
554
555//----------------------------------------------------------------------------//
556
557void 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
566void FrustumFieldMapping::voxelToWorld(const V3d &vsP, V3d &wsP) const
567{
568 voxelToWorld(vsP, wsP, 0.0);
569}
570
571//----------------------------------------------------------------------------//
572
573void 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
582void FrustumFieldMapping::worldToLocal(const V3d &wsP, V3d &lsP) const
583{
584 worldToLocal(wsP, lsP, 0.0);
585}
586
587//----------------------------------------------------------------------------//
588
589void FrustumFieldMapping::worldToLocal(const V3d &wsP, V3d &lsP, float time) const
590{
591 switch (m_zDistribution) {
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
618void FrustumFieldMapping::localToWorld(const V3d &lsP, V3d &wsP) const
619{
620 localToWorld(lsP, wsP, 0.0);
621}
622
623//----------------------------------------------------------------------------//
624
625void FrustumFieldMapping::localToWorld(const V3d &lsP, V3d &wsP, float time) const
626{
627 switch (m_zDistribution) {
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
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
728V3d 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
794
795//----------------------------------------------------------------------------//
796
798{
799 return Ptr(new FrustumFieldMapping(*this));
800}
801
802//----------------------------------------------------------------------------//
803
805
806//----------------------------------------------------------------------------//
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 ...
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 ...
Contains the FieldMapping base class and the NullFieldMapping and MatrixFieldMapping subclasses.
Contains Field, WritableField and ResizableField classes.
double discToCont(int discCoord)
Goes from discrete coordinates to continuous coordinates See Graphics Gems - What is a pixel.
Definition Field.h:1070
#define FIELD_DYNAMIC_CAST
Definition RefCount.h:271
Imath::Box3d Box3d
Definition SpiMathLib.h:79
Imath::V3i V3i
Definition SpiMathLib.h:71
Imath::V3d V3d
Definition SpiMathLib.h:74
#define FIELD3D_EXTRACT_SHRT
Definition SpiMathLib.h:93
#define FIELD3D_LERP
Definition SpiMathLib.h:91
Imath::Box3i Box3i
Definition SpiMathLib.h:77
#define FIELD3D_LERPFACTOR
Definition SpiMathLib.h:92
Imath::M44d M44d
Definition SpiMathLib.h:82
Contains typedefs for the commonly used types in Field3D.
void addSample(const float t, const T &value)
Adds a sample point to the curve.
Definition Curve.h:189
size_t numSamples() const
Returns the number of samples in the curve.
Definition Curve.h:116
const SampleVec & samples() const
Returns a const reference to the samples in the curve.
Definition Curve.h:120
void clear()
Clears all samples in curve.
Definition Curve.h:124
T linear(const float t) const
Linearly interpolates a value from the curve.
Definition Curve.h:216
std::vector< Sample > SampleVec
Definition Curve.h:102
Base class for mapping between world-, local- and voxel coordinates.
V3d m_origin
The integer voxel-space origin of the underlying Field object. Is equal to field.extents....
virtual ~FieldMapping()
Destructor.
virtual std::string className() const =0
Returns the FieldMapping type name. Used when writing/reading from disk.
FieldMapping()
Constructor.
virtual void extentsChanged()
Implement this if the subclass needs to update itself when the resolution changes.
boost::intrusive_ptr< FieldMapping > Ptr
V3d m_res
The integer voxel-space resolution of the underlying Field object. Is equal to field....
void setExtents(const Box3i &extents)
This sets the field extents information to use for defining the local coordinate space.
void voxelToLocal(const V3d &vsP, V3d &lsP) const
Inverse of 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...
static const char * staticClassType()
MatrixCurve m_lpsToWsCurve
Time-varying local perspective to world space transform. Computed from m_ssToWsCurve.
virtual void localToWorld(const V3d &lsP, V3d &wsP) const
Transform from local space position into world space.
bool m_defaultState
Boolean to tell us if the mapping is in its 'default' state. This is needed because the class has a d...
virtual V3d wsVoxelSize(int i, int j, int k) const
Returns world-space size of a voxel at the specified coordinate.
virtual void extentsChanged()
Implement this if the subclass needs to update itself when the resolution changes.
void setTransforms(const M44d &ssToWs, const M44d &csToWs)
Sets the screenToWorld and cameraToWorld transforms. All other internal matrices will be updated base...
void clearCurves()
Clears all Curve data members. Used by setTransforms() to prepare for the first sample to be added.
MatrixCurve m_ssToWsCurve
Time-varying local perspective to world space transform This is not used in calculations,...
void getLocalToVoxelMatrix(M44d &result)
FloatCurve m_farCurve
Time-varying far plane. Computed from m_lpsToWsCurve.
std::vector< V3d > m_wsVoxelSize
Precomputed world-space voxel size. Calculations may assume orthogonal transformation for efficiency.
void reset()
Resets the transform. Makes a perspective transform at the origin, looking down the negative Z axis w...
void computeVoxelSize()
Updates the local to world transformation matrix.
virtual void voxelToWorld(const V3d &vsP, V3d &wsP) const
Transform from voxel space position into world space.
virtual void worldToLocal(const V3d &wsP, V3d &lsP) const
Transform from world space position into local space.
boost::intrusive_ptr< FrustumFieldMapping > Ptr
Convenience typedef.
FloatCurve m_nearCurve
Time-varying near plane. Computed from m_lpsToWsCurve.
ZDistribution m_zDistribution
Slice distribution type.
virtual std::string className() const
Returns the FieldMapping type name. Used when writing/reading from disk.
virtual void worldToVoxel(const V3d &wsP, V3d &vsP) const
Transform from world space position into voxel space.
static const char * staticClassType()
virtual bool isIdentical(FieldMapping::Ptr other, double tolerance=0.0) const
Whether the mapping is identical to another mapping.
virtual FieldMapping::Ptr clone() const
Returns a pointer to a copy of the mapping, pure virtual so ensure derived classes properly implement...
MatrixCurve m_csToWsCurve
Time-varying camera to world space transform.
MatrixCurve m_vsToWsCurve
Time-varying voxel to world space transform.
void setLocalToWorld(const M44d &lsToWs)
Sets the local to world transform. All other matrices will be updated based on this.
virtual std::string className() const
Returns the FieldMapping type name. Used when writing/reading from disk.
static const char * staticClassType()
virtual FieldMapping::Ptr clone() const
Returns a pointer to a copy of the mapping, pure virtual so ensure derived classes properly implement...
virtual bool isIdentical(FieldMapping::Ptr other, double tolerance=0.0) const
Whether the mapping is identical to another mapping.
M44d m_wsToVs
World space to voxel space.
M44d m_wsToLs
World space to local space.
bool m_isTimeVarying
Stores whether the curve has more than one time sample.
void makeIdentity()
Sets the transform to identity. This makes it functionally equivalent to a NullFieldMapping.
boost::intrusive_ptr< MatrixFieldMapping > Ptr
Convenience typedef.
virtual void extentsChanged()
Implement this if the subclass needs to update itself when the resolution changes.
M44d m_vsToWs
Voxel space to world space.
MatrixCurve m_lsToWsCurve
Time-varying local to world space transform.
V3d m_wsVoxelSize
Precomputed world-space voxel size. Calculations may assume orthogonal transformation for efficiency.
void updateTransform()
Updates the local to world transformation matrix.
M44d m_lsToWs
Local space to world space.
void getLocalToVoxelMatrix(M44d &result)
virtual bool isIdentical(FieldMapping::Ptr other, double tolerance=0.0) const
Whether the mapping is identical to another mapping.
boost::intrusive_ptr< NullFieldMapping > Ptr
Convenience typedef.
virtual std::string className() const
Returns the FieldMapping type name. Used when writing/reading from disk.
virtual FieldMapping::Ptr clone() const
Returns a pointer to a copy of the mapping, pure virtual so ensure derived classes properly implement...
static const char * staticClassType()
bool checkMatricesIdentical(const Matrix_T &m1, const Matrix_T &m2, double tolerance)
const string k_mappingName("FieldMapping")
const string k_nullMappingName("NullFieldMapping")
const string k_matrixMappingName("MatrixFieldMapping")
const string k_frustumMappingName("FrustumFieldMapping")
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
Definition ns.h:60