// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // clang-format off #include "stdafx.h" // clang-format on #include <frantic/volumetrics/levelset/rle_index_spec.hpp> using namespace std; using namespace boost; namespace frantic { namespace volumetrics { namespace levelset { /////////////////////////// // rle_scanline_defined_iteration_primitive implementation /////////////////////////// bool rle_scanline_defined_iteration_primitive::init( const rle_index_spec& /*ris*/, const run_data* rdBegin, const run_data* rdEnd, boost::int32_t& outXCurrent, boost::int32_t& outDataIndex ) { for( ; rdBegin != rdEnd; ++rdBegin ) { if( rdBegin->dataIndex >= 0 ) { // If we find a defined run, initialize the primitive, and return true m_rd = rdBegin; m_rdEnd = rdEnd; m_xEnd = ( rdBegin + 1 )->x; outXCurrent = rdBegin->x; outDataIndex = rdBegin->dataIndex; return true; } } // If no defined run was found, clear to an invalid state, and return false clear(); return false; } bool rle_scanline_defined_iteration_primitive::init( const rle_index_spec& ris, const run_data* rdBegin, const run_data* rdEnd, boost::int32_t& outXCurrent, boost::int32_t& outXNegDataIndex, boost::int32_t& outDataIndex, boost::int32_t& outXPosDataIndex ) { int32_t dataIndexPrevious = ris.get_exterior_region_code(); for( ; rdBegin != rdEnd; ++rdBegin ) { if( rdBegin->dataIndex >= 0 ) { // If we find a defined run, initialize the primitive, and return true m_rd = rdBegin; m_rdEnd = rdEnd; m_xEnd = ( rdBegin + 1 )->x; outXCurrent = rdBegin->x; outXNegDataIndex = dataIndexPrevious; outDataIndex = rdBegin->dataIndex; if( outXCurrent + 1 < m_xEnd ) { // If the run has more than one voxel in it, its just the next data index outXPosDataIndex = outDataIndex + 1; } else { // otherwise look at the next run, and if it's not past-the-end, its the starting data // index of that run, otherwise it's the exterior region code ++rdBegin; if( rdBegin != rdEnd ) outXPosDataIndex = rdBegin->dataIndex; else outXPosDataIndex = ris.get_exterior_region_code(); } return true; } else { // Save the undefined region code for the data index in the negative X direction dataIndexPrevious = rdBegin->dataIndex; } } // If no defined run was found, clear to an invalid state, and return false clear(); return false; } void rle_scanline_defined_iteration_primitive::clear() { m_rd = 0; m_rdEnd = 0; m_xEnd = numeric_limits<boost::int32_t>::min(); } bool rle_scanline_defined_iteration_primitive::jump_to_next_defined_x( const rle_index_spec& /*ris*/, boost::int32_t& xTarget, boost::int32_t& xCurrent, boost::int32_t& dataIndex ) { // cout << "xCurrent: " << xCurrent << ", m_dataIndex: " << m_dataIndex << endl; //++xCurrent; if( xTarget < m_xEnd ) { // we can just move directly there // dataIndex is always assumed to be nonnegative for this iteration primitive dataIndex += xTarget - xCurrent; return true; } else if( m_rd != m_rdEnd ) { ++m_rd; for( ; m_rd != m_rdEnd; ++m_rd ) { if( m_rd->dataIndex >= 0 ) { // If we find a defined run, set the necessary variables return true dataIndex = m_rd->dataIndex; m_xEnd = ( m_rd + 1 )->x; xCurrent = m_rd->x; // if we overshoot, then we stop and report where we actually are if( xCurrent > xTarget ) { return false; } else if( xCurrent == xTarget ) { // we have found the target return true; } // otherwise we need to jump to it else if( xTarget < m_xEnd ) { // we can just move directly there // dataIndex is always assumed to be nonnegative for this iteration primitive dataIndex += xTarget - xCurrent; return true; } // else keep searching } } } // If we found no defined X, set rd and rdEnd to NULL to signal that this->finished() should return true. m_rd = 0; m_rdEnd = 0; return false; } bool rle_scanline_defined_iteration_primitive::increment_to_next_defined_x( const rle_index_spec& /*ris*/, boost::int32_t& xCurrent, boost::int32_t& dataIndex ) { // cout << "xCurrent: " << xCurrent << ", m_dataIndex: " << m_dataIndex << endl; ++xCurrent; if( xCurrent < m_xEnd ) { // dataIndex is always assumed to be nonnegative for this iteration primitive ++dataIndex; return true; } else if( m_rd != m_rdEnd ) { ++m_rd; for( ; m_rd != m_rdEnd; ++m_rd ) { if( m_rd->dataIndex >= 0 ) { // If we find a defined run, set the necessary variables return true dataIndex = m_rd->dataIndex; m_xEnd = ( m_rd + 1 )->x; xCurrent = m_rd->x; return true; } } } // If we found no defined X, set rd and rdEnd to NULL to signal that this->finished() should return true. m_rd = 0; m_rdEnd = 0; return false; } bool rle_scanline_defined_iteration_primitive::increment_to_next_defined_x( const rle_index_spec& ris, boost::int32_t& xCurrent, boost::int32_t& outXNegDataIndex, boost::int32_t& dataIndex, boost::int32_t& outXPosDataIndex ) { // cout << "xCurrent: " << xCurrent << ", m_dataIndex: " << m_dataIndex << endl; ++xCurrent; if( xCurrent < m_xEnd ) { // dataIndex is always assumed to be nonnegative for this iteration primitive outXNegDataIndex = dataIndex; ++dataIndex; if( xCurrent + 1 < m_xEnd ) { // If the next voxel is still in the same run, its just the next data index outXPosDataIndex = dataIndex + 1; } else { // otherwise look at the next run, and if it's not past-the-end, its the starting data // index of that run, otherwise it's the exterior region code const run_data* rd = m_rd + 1; if( rd != m_rdEnd ) outXPosDataIndex = rd->dataIndex; else outXPosDataIndex = ris.get_exterior_region_code(); } return true; } else if( m_rd != m_rdEnd ) { int32_t dataIndexPrevious = ris.get_exterior_region_code(); ++m_rd; for( ; m_rd != m_rdEnd; ++m_rd ) { if( m_rd->dataIndex >= 0 ) { // If we find a defined run, set the necessary variables return true m_xEnd = ( m_rd + 1 )->x; xCurrent = m_rd->x; outXNegDataIndex = dataIndexPrevious; dataIndex = m_rd->dataIndex; if( xCurrent + 1 < m_xEnd ) { // If the run has more than one voxel in it, its just the next data index outXPosDataIndex = dataIndex + 1; } else { // otherwise look at the next run, and if it's not past-the-end, its the starting data // index of that run, otherwise it's the exterior region code const run_data* rd = m_rd + 1; if( rd != m_rdEnd ) outXPosDataIndex = rd->dataIndex; else outXPosDataIndex = ris.get_exterior_region_code(); } return true; } else { // Save the undefined region code for the data index in the negative X direction dataIndexPrevious = m_rd->dataIndex; } } } // If we found no defined X, set rd and rdEnd to NULL to signal that this->finished() should return true. m_rd = 0; m_rdEnd = 0; return false; } /////////////////////////// // rle_scanline_iteration_primitive implementation /////////////////////////// void rle_scanline_iteration_primitive::init( const rle_index_spec& ris, boost::int32_t b, boost::int32_t c, boost::int32_t xCurrent, boost::int32_t& outDataIndex ) { int32_t bsize = ris.m_abcCoordSize.ysize(), csize = ris.m_abcCoordSize.zsize(); if( (uint32_t)b < (uint32_t)bsize && (uint32_t)c < (uint32_t)csize ) { int32_t bcIndex = b + c * bsize; const int32_t* bcToRI = &ris.m_bcToRunIndex[bcIndex]; const run_data* rd = &ris.m_runData[*bcToRI]; const run_data* rdEnd = rd + *( bcToRI + 1 ) - *bcToRI - 1; if( xCurrent < rd->x ) { // If this is before the first run, set up xEnd to start at the first run in the range outDataIndex = ris.get_exterior_region_code(); m_rd = rd - 1; m_rdEnd = rdEnd; m_xEnd = rd->x; } else { while( rd != rdEnd && xCurrent >= ( rd + 1 )->x ) ++rd; if( rd != rdEnd ) { outDataIndex = rd->dataIndex; if( outDataIndex >= 0 ) { outDataIndex += xCurrent - rd->x; } m_rd = rd; m_rdEnd = rdEnd; m_xEnd = ( rd + 1 )->x; } else { outDataIndex = ris.get_exterior_region_code(); m_rd = 0; m_rdEnd = 0; } } } else { outDataIndex = ris.get_exterior_region_code(); m_rd = 0; m_rdEnd = 0; } } void rle_scanline_iteration_primitive::clear() { m_rd = 0; m_rdEnd = 0; } void rle_scanline_iteration_primitive::increment_to_x( boost::int32_t xPrevious, boost::int32_t xNew, const rle_index_spec& ris, boost::int32_t& dataIndex ) { // Once m_rd is zero, the data index never changes from the exterior region code if( m_rd != 0 ) { if( xNew < m_xEnd ) { // If we're within the same run, then increment dataIndex if it's a defined run if( dataIndex >= 0 ) dataIndex += xNew - xPrevious; } else { // Need to find a new run while( m_rd != m_rdEnd && xNew >= ( m_rd + 1 )->x ) ++m_rd; if( m_rd != m_rdEnd ) { dataIndex = m_rd->dataIndex; if( dataIndex >= 0 ) { dataIndex += xNew - m_rd->x; } m_xEnd = ( m_rd + 1 )->x; } else { // We've passed the end of all the runs, so from now on everything is the exterior region code dataIndex = ris.get_exterior_region_code(); m_rd = 0; m_rdEnd = 0; } } } } } // namespace levelset } // namespace volumetrics } // namespace frantic