// ---------------------------------------------------------------------------- Get_Alpha_Neighborhood()
LWTypes::LWDVector Simplex_Noise::Get_Alpha_Neighborhood ( LWTypes::LWNodalAccess * nodal_access )
{
// NOTE: Is only accessed by Alpha_Bump, so is not cached. Calculate directly.
// Determine offset of nearby coordinates
const double epsilon = Neighborhod_Epsilon( nodal_access );
// Generate the three neighborhood coordinates
const LWTypes::LWDVector object_spot( nodal_access->oPos );
const LWTypes::LWDVector world_spot ( nodal_access->wPos );
LWTypes::LWDVector object_neighbor_X( object_spot.X() + epsilon, object_spot.Y(), object_spot.Z() );
LWTypes::LWDVector object_neighbor_Y( object_spot.X(), object_spot.Y() + epsilon, object_spot.Z() );
LWTypes::LWDVector object_neighbor_Z( object_spot.X(), object_spot.Y(), object_spot.Z() + epsilon );
LWTypes::LWDVector world_neighbor_X ( world_spot.X() + epsilon, world_spot.Y(), world_spot.Z() );
LWTypes::LWDVector world_neighbor_Y ( world_spot.X(), world_spot.Y() + epsilon, world_spot.Z() );
LWTypes::LWDVector world_neighbor_Z ( world_spot.X(), world_spot.Y(), world_spot.Z() + epsilon );
// Backup existing spot locations
double oPos_backup[3];
double wPos_backup[3];
memcpy( oPos_backup, nodal_access->oPos, sizeof(double) * 3 );
memcpy( wPos_backup, nodal_access->wPos, sizeof(double) * 3 );
// Sample alpha foreground and background at offset locations
auto Update_Coordinates = [&]( LWTypes::LWDVector object_neighbor,
LWTypes::LWDVector world_neighbor )
{
memcpy( nodal_access->oPos, (double*)object_neighbor, sizeof(double) * 3 );
memcpy( nodal_access->wPos, (double*)world_neighbor, sizeof(double) * 3 );
};
auto Get_Alpha_from_Offset = [&]( const Input_Scalar_t & Input,
LWTypes::LWDVector object_neighbor,
LWTypes::LWDVector world_neighbor ) -> double
{
Update_Coordinates( object_neighbor, world_neighbor );
return Input.Get( nodal_access );
};
const double alpha_fg_neighbor_X = Get_Alpha_from_Offset( Input_Alpha_Foreground, object_neighbor_X, world_neighbor_X );
const double alpha_fg_neighbor_Y = Get_Alpha_from_Offset( Input_Alpha_Foreground, object_neighbor_Y, world_neighbor_Y );
const double alpha_fg_neighbor_Z = Get_Alpha_from_Offset( Input_Alpha_Foreground, object_neighbor_Z, world_neighbor_Z );
const double alpha_bg_neighbor_X = Get_Alpha_from_Offset( Input_Alpha_Background, object_neighbor_X, world_neighbor_X );
const double alpha_bg_neighbor_Y = Get_Alpha_from_Offset( Input_Alpha_Background, object_neighbor_Y, world_neighbor_Y );
const double alpha_bg_neighbor_Z = Get_Alpha_from_Offset( Input_Alpha_Background, object_neighbor_Z, world_neighbor_Z );
// Restore spot locations
memcpy( nodal_access->oPos, oPos_backup, sizeof(double) * 3 );
memcpy( nodal_access->wPos, wPos_backup, sizeof(double) * 3 );
// Get noise neighborhood for mixing amounts
const Simplex_Neighborhood_t noise_neighborhood( Get_Noise_Neighborhood(nodal_access) );
// Mix alpha amounts and return
return LWTypes::LWDVector ( LERP( noise_neighborhood.Noise_X(), alpha_bg_neighbor_X, alpha_fg_neighbor_X ),
LERP( noise_neighborhood.Noise_Y(), alpha_bg_neighbor_Y, alpha_fg_neighbor_Y ),
LERP( noise_neighborhood.Noise_Z(), alpha_bg_neighbor_Z, alpha_fg_neighbor_Z ) );
}