MACFieldUtil.h
Go to the documentation of this file.
//----------------------------------------------------------------------------//
/*
* Copyright (c) 2009 Sony Pictures Imageworks Inc
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution. Neither the name of Sony Pictures Imageworks nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//
#ifndef _INCLUDED_Field3D_MACFieldUtil_H_
#define _INCLUDED_Field3D_MACFieldUtil_H_
#include "MACField.h"
//----------------------------------------------------------------------------//
#include "ns.h"
FIELD3D_NAMESPACE_OPEN
//----------------------------------------------------------------------------//
// Utility functions
//----------------------------------------------------------------------------//
template <class Data_T, class Field_T>
void convertMACToCellCentered(typename MACField<Data_T>::Ptr mac,
typename Field_T::Ptr cc);
//----------------------------------------------------------------------------//
template <class Field_T, class Data_T>
void convertCellCenteredToMAC(typename Field_T::Ptr cc,
typename MACField<Data_T>::Ptr mac);
//----------------------------------------------------------------------------//
// Implementations
//----------------------------------------------------------------------------//
template <class Data_T, class Field_T>
void convertMACToCellCentered(typename MACField<Data_T>::Ptr mac,
typename Field_T::Ptr cc)
{
// Make sure the extents and data window match
if (cc->extents().min != mac->extents().min ||
cc->extents().max != mac->extents().max ||
cc->dataWindow().min != mac->dataWindow().min ||
cc->dataWindow().max != mac->dataWindow().max ) {
cc->setSize(mac->extents(), mac->dataWindow());
}
// Make sure mapping matches
if (!cc->mapping()->isIdentical(mac->mapping())) {
cc->setMapping(mac->mapping());
}
// MAC velocities are in simulation space (axis-aligned to the
// mapping) because the values are stored on the faces, so rotate
// vectors from simulation-space to world-space when transferring
// from MAC to cell-centered
bool rotateVector = false;
M44d ssToWsMtx;
MatrixFieldMapping::Ptr mapping =
FIELD_DYNAMIC_CAST<MatrixFieldMapping>(mac->mapping());
if (mapping) {
M44d localToWorldMtx = mapping->localToWorld();
V3d scale, rot, trans, shear;
if (extractSHRT(localToWorldMtx, scale, shear, rot, trans, false)) {
ssToWsMtx.rotate(rot);
if (rot.length2() > FLT_EPSILON)
rotateVector = true;
}
}
// Loop over all the voxels in the output field ---
typename Field_T::iterator i = cc->begin();
typename Field_T::iterator end = cc->end();
if (rotateVector) {
for (; i != end; ++i) {
*i = mac->value(i.x, i.y, i.z) * ssToWsMtx;
}
} else {
for (; i != end; ++i) {
*i = mac->value(i.x, i.y, i.z);
}
}
}
//----------------------------------------------------------------------------//
template <class Field_T, class Data_T>
void convertCellCenteredToMAC(typename Field_T::Ptr cc,
typename MACField<Data_T>::Ptr mac)
{
// Make sure the extents and data window match
if (mac->extents().min != cc->extents().min ||
mac->extents().max != cc->extents().max ||
mac->dataWindow().min != cc->dataWindow().min ||
mac->dataWindow().max != cc->dataWindow().max ) {
mac->setSize(cc->extents(), cc->dataWindow());
}
// Make sure mapping matches
if (!mac->mapping()->isIdentical(cc->mapping())) {
mac->setMapping(cc->mapping());
}
Box3i data = mac->dataWindow();
// MAC velocities are in simulation space (axis-aligned to the
// mapping) because the values are stored on the faces, so rotate
// vectors from world-space to simulation-space when transferring
// from cell-centered to MAC
bool rotateVector = false;
M44d wsToSsMtx;
MatrixFieldMapping::Ptr mapping =
FIELD_DYNAMIC_CAST<MatrixFieldMapping>(mac->mapping());
if (mapping) {
M44d localToWorld = mapping->localToWorld();
V3d scale, rot, trans, shear;
if (FIELD3D_EXTRACT_SHRT(localToWorld, scale, shear, rot, trans, false)) {
wsToSsMtx.rotate(-rot);
rotateVector = true;
}
}
// Use a pointer to a field below so we can substitute it out for
// our intermediate, rotated field if necessary, without needing to
// duplicate the loops. This should be more efficient CPU-wise so
// we don't need to do 3 matrix multiplies per cell-centered voxel
// because it's used in 3 separate loops (1 per MAC face).
typename Field_T::Ptr src = cc;
typename Field_T::Ptr ccRotated;
if (rotateVector) {
ccRotated =
typename Field_T::Ptr(new Field_T);
ccRotated->matchDefinition(cc);
typename Field_T::const_iterator iIn = cc->cbegin();
typename Field_T::const_iterator endIn = cc->cend();
typename Field_T::iterator iOut = ccRotated->begin();
for (; iIn != endIn; ++iIn, ++iOut) {
*iOut = *iIn * wsToSsMtx;
}
src = ccRotated;
}
// Set the u edge value to their closest voxel
for (int k = data.min.z; k <= data.max.z; k++) {
for (int j = data.min.y; j <= data.max.y; j++) {
mac->u(data.min.x, j, k) = src->value(data.min.x, j, k).x;
mac->u(data.max.x + 1, j, k) = src->value(data.max.x, j, k).x;
}
}
// Set the v edge value to their closest voxel
for (int k = data.min.z; k <= data.max.z; k++) {
for (int i = data.min.x; i <= data.max.x; i++) {
mac->v(i, data.min.y, k) = src->value(i, data.min.y, k).y;
mac->v(i, data.max.y + 1, k) = src->value(i, data.max.y, k).y;
}
}
// Set the w edge value to their closest voxel
for (int j = data.min.y; j <= data.max.y; j++) {
for (int i = data.min.x; i <= data.max.x; i++) {
mac->w(i, j, data.min.z) = src->value(i, j, data.min.z).z;
mac->w(i, j, data.max.z + 1) = src->value(i, j, data.max.z).z;
}
}
// Loop over internal u values
for (int k = data.min.z; k <= data.max.z; ++k) {
for (int j = data.min.y; j <= data.max.y; ++j) {
for (int i = data.min.x + 1; i <= data.max.x; ++i) {
mac->u(i, j, k) =
(src->value(i, j, k).x + src->value(i - 1, j, k).x) * 0.5;
}
}
}
// Loop over internal v values
for (int k = data.min.z; k <= data.max.z; ++k) {
for (int j = data.min.y + 1; j <= data.max.y; ++j) {
for (int i = data.min.x; i <= data.max.x; ++i) {
mac->v(i, j, k) =
(src->value(i, j, k).y + src->value(i, j - 1, k).y) * 0.5;
}
}
}
// Loop over internal w values
for (int k = data.min.z + 1; k <= data.max.z; ++k) {
for (int j = data.min.y; j <= data.max.y; ++j) {
for (int i = data.min.x; i <= data.max.x; ++i) {
mac->w(i, j, k) =
(src->value(i, j, k).z + src->value(i, j, k - 1).z) * 0.5;
}
}
}
}
//----------------------------------------------------------------------------//
FIELD3D_NAMESPACE_HEADER_CLOSE
//----------------------------------------------------------------------------//
#endif // Include guard
convertMACToCellCentered
FIELD3D_NAMESPACE_OPEN void convertMACToCellCentered(typename MACField< Data_T >::Ptr mac, typename Field_T::Ptr cc)
Converts the MAC field to a cell-centered field.
Definition MACFieldUtil.h:78
convertCellCenteredToMAC
void convertCellCenteredToMAC(typename Field_T::Ptr cc, typename MACField< Data_T >::Ptr mac)
Converts the cell-centered field to a MAC field.
Definition MACFieldUtil.h:132
MACField.h
Contains the MACField class.
FIELD_DYNAMIC_CAST
#define FIELD_DYNAMIC_CAST
Definition RefCount.h:271
V3d
Imath::V3d V3d
Definition SpiMathLib.h:74
FIELD3D_EXTRACT_SHRT
#define FIELD3D_EXTRACT_SHRT
Definition SpiMathLib.h:93
Box3i
Imath::Box3i Box3i
Definition SpiMathLib.h:77
M44d
Imath::M44d M44d
Definition SpiMathLib.h:82
FieldRes::setMapping
void setMapping(FieldMapping::Ptr mapping)
Sets the field's mapping.
Definition Field.h:347
FieldRes::mapping
FieldMapping::Ptr mapping()
Returns a pointer to the mapping.
Definition Field.h:263
FieldRes::extents
const Box3i & extents() const
Returns the extents of the data. This signifies the relevant area that the data exists over....
Definition Field.h:249
FieldRes::dataWindow
const Box3i & dataWindow() const
Returns the data window. Any coordinate inside this window is safe to pass to value() in the Field su...
Definition Field.h:253
MACField::w
const real_t & w(int i, int j, int k) const
Read access to value on w-facing wall.
Definition MACField.h:774
MACField::u
const real_t & u(int i, int j, int k) const
Read access to value on u-facing wall.
Definition MACField.h:698
MACField::Ptr
boost::intrusive_ptr< MACField > Ptr
Definition MACField.h:101
MACField::value
virtual Data_T value(int i, int j, int k) const
Definition MACField.h:630
MACField::v
const real_t & v(int i, int j, int k) const
Read access to value on v-facing wall.
Definition MACField.h:736
MatrixFieldMapping::Ptr
boost::intrusive_ptr< MatrixFieldMapping > Ptr
Convenience typedef.
Definition FieldMapping.h:341
ResizableField::setSize
void setSize(const V3i &size)
Resizes the object.
Definition Field.h:913
FIELD3D_NAMESPACE_OPEN
Definition FieldMapping.cpp:74
ns.h
FIELD3D_NAMESPACE_HEADER_CLOSE
#define FIELD3D_NAMESPACE_HEADER_CLOSE
Definition ns.h:58