Field3D
FieldMapping.cpp
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------//
00002 
00003 /*
00004  * Copyright (c) 2009 Sony Pictures Imageworks Inc
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  *
00012  * Redistributions of source code must retain the above copyright
00013  * notice, this list of conditions and the following disclaimer.
00014  * Redistributions in binary form must reproduce the above copyright
00015  * notice, this list of conditions and the following disclaimer in the
00016  * documentation and/or other materials provided with the
00017  * distribution.  Neither the name of Sony Pictures Imageworks nor the
00018  * names of its contributors may be used to endorse or promote
00019  * products derived from this software without specific prior written
00020  * permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
00026  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00029  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00031  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00033  * OF THE POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00036 //----------------------------------------------------------------------------//
00037 
00043 //----------------------------------------------------------------------------//
00044 
00045 #include <iostream>
00046 #include <vector>
00047 
00048 #include "FieldMapping.h"
00049 #include "Types.h"
00050 
00051 //----------------------------------------------------------------------------//
00052 
00053 using namespace boost;
00054 using namespace std;
00055 
00056 //----------------------------------------------------------------------------//
00057 
00058 FIELD3D_NAMESPACE_OPEN
00059 
00060 //----------------------------------------------------------------------------//
00061 // Field3D namespaces
00062 //----------------------------------------------------------------------------//
00063 
00064 
00065 //----------------------------------------------------------------------------//
00066 // Local namespace
00067 //----------------------------------------------------------------------------//
00068 
00069 namespace {
00070   const string k_nullMappingName("NullFieldMapping");
00071   const string k_matrixMappingName("MatrixFieldMapping");
00072   const string k_frustumMappingName("FrustumFieldMapping");
00073 }
00074 
00075 //----------------------------------------------------------------------------//
00076 // FieldMapping
00077 //----------------------------------------------------------------------------//
00078 
00079 FieldMapping::FieldMapping()
00080   : RefBase(), 
00081     m_origin(V3i(0)),
00082     m_res(V3i(1))
00083 { 
00084   /* Empty */ 
00085 }
00086 
00087 //----------------------------------------------------------------------------//
00088 
00089 FieldMapping::FieldMapping(const Box3i &extents)
00090   : RefBase()
00091 { 
00092   setExtents(extents);
00093 }
00094 
00095 //----------------------------------------------------------------------------//
00096 
00097 FieldMapping::~FieldMapping()
00098 { 
00099   /* Empty */ 
00100 }
00101 
00102 //----------------------------------------------------------------------------//
00103 
00104 void FieldMapping::setExtents(const Box3i &extents)
00105 { 
00106   m_origin = extents.min;
00107   m_res = extents.max - extents.min + V3i(1);
00108   extentsChanged();
00109 }
00110 
00111 //----------------------------------------------------------------------------//
00112 
00113 void FieldMapping::localToVoxel(const V3d &lsP, V3d &vsP) const
00114 { 
00115   vsP = m_origin + lsP * m_res;
00116 }
00117 
00118 //----------------------------------------------------------------------------//
00119 
00120 void FieldMapping::localToVoxel(const V3d &lsP, V3d &vsP,
00121                                 float /*time*/) const
00122 { 
00123   vsP = m_origin + lsP * m_res;
00124 }
00125 
00126 //----------------------------------------------------------------------------//
00127 
00128 void FieldMapping::localToVoxel(std::vector<V3d>::const_iterator lsP, 
00129                                 std::vector<V3d>::const_iterator end, 
00130                                 std::vector<V3d>::iterator vsP) const
00131 { 
00132   for (; lsP != end; ++lsP, ++vsP) {
00133     *vsP = m_origin + *lsP * m_res;
00134   }
00135 }
00136 //----------------------------------------------------------------------------//
00137 
00138 void FieldMapping::voxelToLocal(const V3d &vsP, V3d &lsP) const
00139 { 
00140   lsP.x = FIELD3D_LERPFACTOR(vsP.x, m_origin.x, m_origin.x + m_res.x);
00141   lsP.y = FIELD3D_LERPFACTOR(vsP.y, m_origin.y, m_origin.y + m_res.y);
00142   lsP.z = FIELD3D_LERPFACTOR(vsP.z, m_origin.z, m_origin.z + m_res.z);
00143 }
00144 
00145 //----------------------------------------------------------------------------//
00146 // NullFieldMapping
00147 //----------------------------------------------------------------------------//
00148 
00149 std::string NullFieldMapping::className() const
00150 {
00151   return k_nullMappingName;
00152 }
00153 
00154 //----------------------------------------------------------------------------//
00155 
00156 bool NullFieldMapping::isIdentical(FieldMapping::Ptr other, 
00157                                    double tolerance) const
00158 {
00159   // For null mappings it's simple - if the other one is also a null mapping
00160   // then true, otherwise it's false.
00161   
00162   return other->className() == k_nullMappingName;
00163 }
00164 
00165 //----------------------------------------------------------------------------//
00166 
00167 FieldMapping::Ptr NullFieldMapping::clone() const
00168 {
00169   return Ptr(new NullFieldMapping(*this));
00170 }
00171 
00172 //----------------------------------------------------------------------------//
00173 // MatrixFieldMapping
00174 //----------------------------------------------------------------------------//
00175 
00176 MatrixFieldMapping::MatrixFieldMapping()
00177   : FieldMapping()
00178 { 
00179   makeIndentity();
00180 }
00181 
00182 //----------------------------------------------------------------------------//
00183 
00184 MatrixFieldMapping::MatrixFieldMapping(const Box3i &extents)
00185   : FieldMapping(extents)
00186 { 
00187   makeIndentity();
00188 }
00189 
00190 //----------------------------------------------------------------------------//
00191 
00192 void MatrixFieldMapping::setLocalToWorld(const M44d &lsToWs)
00193 {
00194   m_lsToWs = lsToWs;
00195   updateTransform();
00196 }
00197 
00198 //----------------------------------------------------------------------------//
00199 
00200 void MatrixFieldMapping::makeIndentity()
00201 {
00202   m_lsToWs.makeIdentity();
00203   updateTransform();
00204 }
00205 
00206 //----------------------------------------------------------------------------//
00207 
00208 void MatrixFieldMapping::extentsChanged()
00209 { 
00210   updateTransform();
00211 }
00212 
00213 //----------------------------------------------------------------------------//
00214 
00215 std::string MatrixFieldMapping::className() const
00216 {
00217   return k_matrixMappingName;
00218 }
00219 
00220 //----------------------------------------------------------------------------//
00221 
00222 bool MatrixFieldMapping::isIdentical(FieldMapping::Ptr other, 
00223                                      double tolerance) const
00224 {
00225   if (other->className() != k_matrixMappingName) {
00226     return false;
00227   } else {
00228     MatrixFieldMapping::Ptr mm = 
00229       dynamic_pointer_cast<MatrixFieldMapping>(other);
00230     if (mm) {
00231       // first preserve the same test as before:
00232       if (mm->m_lsToWs.equalWithRelError(m_lsToWs, tolerance) && 
00233           mm->m_wsToVs.equalWithRelError(m_wsToVs, tolerance)) {
00234         return true;
00235       }
00236 
00237       // In case of precision problems, do a more robust test by
00238       // decomposing the matrices and comparing the components
00239 
00240       V3d s1, r1, t1, sh1;
00241       V3d s2, r2, t2, sh2;
00242 
00243       // Compare local-to-world matrices
00244       if (!FIELD3D_EXTRACT_SHRT(m_lsToWs, s1, sh1, r1, t1, false)) {
00245         return false;
00246       }
00247       if (!FIELD3D_EXTRACT_SHRT(mm->m_lsToWs, s2, sh2, r2, t2, false)) {
00248         return false;
00249       }
00250       if (!s1.equalWithRelError(s2, tolerance) ||
00251           !r1.equalWithAbsError(r2, tolerance) ||
00252           !t1.equalWithRelError(t2, tolerance)) {
00253         return false;
00254       }
00255 
00256       // Compare world-to-voxel matrices
00257       if (!FIELD3D_EXTRACT_SHRT(m_wsToVs, s1, sh1, r1, t1, false)) {
00258         return false;
00259       }
00260       if (!FIELD3D_EXTRACT_SHRT(mm->m_wsToVs, s2, sh2, r2, t2, false)) {
00261         return false;
00262       }
00263       if (!s1.equalWithRelError(s2, tolerance) ||
00264           !r1.equalWithAbsError(r2, tolerance) ||
00265           !t1.equalWithRelError(t2, tolerance)) {
00266         return false;
00267       }
00268       return true;
00269     } else {
00270       return false;
00271     }
00272   }
00273   return false;
00274 }
00275 
00276 //----------------------------------------------------------------------------//
00277 
00278 void MatrixFieldMapping::updateTransform() 
00279 {
00280   m_wsToLs = m_lsToWs.inverse();
00281   M44d lsToVs;
00282   getLocalToVoxelMatrix(lsToVs);
00283   m_wsToVs = m_wsToLs * lsToVs;
00284   m_vsToWs = m_wsToVs.inverse();
00285 
00286   // Precompute the voxel size
00287   V3d voxelOrigin, nextVoxel;
00288   m_vsToWs.multVecMatrix(V3d(0, 0, 0), voxelOrigin);
00289   m_vsToWs.multVecMatrix(V3d(1, 0, 0), nextVoxel);
00290   m_wsVoxelSize.x = (nextVoxel - voxelOrigin).length();
00291   m_vsToWs.multVecMatrix(V3d(0, 1, 0), nextVoxel);
00292   m_wsVoxelSize.y = (nextVoxel - voxelOrigin).length();
00293   m_vsToWs.multVecMatrix(V3d(0, 0, 1), nextVoxel);
00294   m_wsVoxelSize.z = (nextVoxel - voxelOrigin).length();
00295 }
00296 
00297 //----------------------------------------------------------------------------//
00298 
00299 void MatrixFieldMapping::getLocalToVoxelMatrix(M44d &result)
00300 {
00301   // Local to voxel is a scale by the resolution of the field, offset
00302   // to the origin of the extents
00303   M44d scaling, translation;
00304   scaling.setScale(m_res);
00305   translation.setTranslation(m_origin);
00306   result = scaling * translation;
00307 }
00308 
00309 //----------------------------------------------------------------------------//
00310 
00311 FieldMapping::Ptr MatrixFieldMapping::clone() const
00312 {
00313   return Ptr(new MatrixFieldMapping(*this));
00314 }
00315 
00316 //----------------------------------------------------------------------------//
00317 
00318 FIELD3D_NAMESPACE_SOURCE_CLOSE
00319 
00320 //----------------------------------------------------------------------------//