Skip to content

Commit

Permalink
EdgeHandle : Generalize for cylinder radius
Browse files Browse the repository at this point in the history
  • Loading branch information
ericmehl committed Oct 17, 2023
1 parent e614e7c commit 9d38030
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 65 deletions.
2 changes: 1 addition & 1 deletion Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Features

- LightTool :
- Added manipulator for disk and point light radii.
- Added manipulator for cylinder length.
- Added manipulators for cylinder length and radius.

Improvements
------------
Expand Down
159 changes: 95 additions & 64 deletions src/GafferSceneUI/LightTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2028,24 +2028,31 @@ class EdgeHandle : public LightToolHandle
EdgeHandle(
const std::string &lightType,
SceneView *view,
LightAxis lightAxis,
const InternedString &edgeParameter,
const V3f &edgeAxis,
const float edgeToHandleRatio,
const InternedString &oppositeParameter,
const V3f &oppositeAxis,
const float oppositeToHandleRatio,
const InternedString &oppositeScaleAttributeName,
const float edgeMargin,
const std::string &tipPlugSuffix,
const std::string &name = "EdgeHandle"
) :
LightToolHandle( lightType, view, {edgeParameter, oppositeParameter}, name ),
m_lightAxis( lightAxis ),
m_edgeParameter( edgeParameter ),
m_edgeAxis( edgeAxis ),
m_edgeToHandleRatio( edgeToHandleRatio ),
m_oppositeParameter( oppositeParameter ),
m_oppositeAxis( oppositeAxis ),
m_oppositeToHandleRatio( oppositeToHandleRatio ),
m_scale( 1.f )
m_oppositeScaleAttributeName( oppositeScaleAttributeName ),
m_edgeMargin( edgeMargin ),
m_tipPlugSuffix( tipPlugSuffix ),
m_edgeScale( 1.f ),
m_oppositeScale( 1.f ),
m_orientation(),
m_oppositeAdditionalScale( 1.f )
{
}

Expand All @@ -2056,6 +2063,45 @@ class EdgeHandle : public LightToolHandle

protected :

void handlePathChanged() override
{
/// \todo This can be simplified and some of the logic, especially getting the inspectors, can
/// be moved to the constructor when we standardize on a single USDLux light representation.

ConstCompoundObjectPtr attributes = scene()->fullAttributes( handlePath() );

for( const auto &[attributeName, value] : attributes->members() )
{
if(
StringAlgo::matchMultiple( attributeName, g_lightAttributePattern ) &&
value->typeId() == (IECore::TypeId)ShaderNetworkTypeId
)
{
const auto shader = attributes->member<ShaderNetwork>( attributeName )->outputShader();
std::string shaderAttribute = shader->getType() + ":" + shader->getName();

if( !isLightType( shaderAttribute ) )
{
continue;
}

m_orientation = M44f();
if( auto orientationData = Metadata::value<M44fData>( shaderAttribute, "visualiserOrientation" ) )
{
m_orientation = orientationData->readable();
}

m_oppositeAdditionalScale = 1.f;
if( auto scaleData = Metadata::value<FloatData>( shaderAttribute, m_oppositeScaleAttributeName ) )
{
m_oppositeAdditionalScale = scaleData->readable();
}

break;
}
}
}

bool handleDragMoveInternal( const GafferUI::DragDropEvent &event ) override
{
Inspector::ResultPtr edgeInspection = dragStartInspection( m_edgeParameter );
Expand All @@ -2067,9 +2113,7 @@ class EdgeHandle : public LightToolHandle
const float nonZeroValue = edgeInspection->typedValue<float>( 0.f ) == 0 ? 1.f : edgeInspection->typedValue<float>( 0.f );
const float newValue = m_drag.value().updatedPosition( event ) - m_drag.value().startPosition();

const float scale = m_lightAxis == LightAxis::Width ? m_scale.x : m_scale.y;

float mult = std::max( ( newValue * 2.f ) / ( nonZeroValue * scale ) + 1.f, 0.f );
float mult = std::max( ( newValue * m_edgeToHandleRatio ) / ( nonZeroValue * m_edgeScale ) + 1.f, 0.f );

applyMultiplier( m_edgeParameter, mult );

Expand All @@ -2078,7 +2122,8 @@ class EdgeHandle : public LightToolHandle

void updateLocalTransformInternal( const V3f &scale, const V3f & ) override
{
m_scale = V2f( scale.x, scale.y );
m_edgeScale = abs( scale.dot( m_edgeAxis * m_orientation ) );
m_oppositeScale = abs( scale.dot( m_oppositeAxis * m_orientation ) ) * m_oppositeAdditionalScale;
}

bool handleDragEndInternal() override
Expand All @@ -2095,8 +2140,7 @@ class EdgeHandle : public LightToolHandle
}

Inspector::ResultPtr edgeInspection = handleInspection( m_edgeParameter );
Inspector::ResultPtr oppositeInspection = handleInspection( m_oppositeParameter );
if( !edgeInspection || !oppositeInspection )
if( !edgeInspection )
{
return;
}
Expand All @@ -2117,7 +2161,7 @@ class EdgeHandle : public LightToolHandle

LineSegment3f edgeSegment = this->edgeSegment(
edgeInspection->typedValue<float>( 0.f ),
oppositeInspection->typedValue<float>( 0.f )
oppositeInspectionValue()
);

M44f edgeTransform;
Expand All @@ -2141,11 +2185,12 @@ class EdgeHandle : public LightToolHandle
edgeGroup->setTransform( edgeTransform );

rootGroup->addChild( edgeGroup );
rootGroup->setTransform( m_orientation );
}

void setupDrag( const DragDropEvent &event ) override
{
m_drag = LinearDrag( this, LineSegment3f( V3f( 0 ), m_edgeAxis ), event );
m_drag = LinearDrag( this, LineSegment3f( V3f( 0 ), m_edgeAxis * m_orientation ), event );
}

std::vector<const Inspector::Result *> handleValueInspections() const override
Expand All @@ -2167,7 +2212,7 @@ class EdgeHandle : public LightToolHandle

std::string tipPlugSuffix() const override
{
return m_lightAxis == LightAxis::Width ? "widths" : "heights";
return m_tipPlugSuffix;
}

std::string tipInfoSuffix() const override
Expand All @@ -2183,27 +2228,32 @@ class EdgeHandle : public LightToolHandle
}

Inspector::ResultPtr edgeInspection = handleInspection( m_edgeParameter );
Inspector::ResultPtr oppositeInspection = handleInspection( m_oppositeParameter );
if( !edgeInspection || !oppositeInspection )
if( !edgeInspection )
{
return;
}

LineSegment3f edgeSegment = this->edgeSegment( edgeInspection->typedValue<float>( 0.f ), oppositeInspection->typedValue<float>( 0.f ) );
LineSegment3f edgeSegment = this->edgeSegment( edgeInspection->typedValue<float>( 0.f ), oppositeInspectionValue() );
V3f offset = edgeToGadgetSpace( edgeInspection->typedValue<float>( 0.f ) );
edgeSegment.p0 += offset;
edgeSegment.p1 += offset;
edgeSegment *= m_orientation;

V3f eventClosest;
setTooltipPosition( edgeSegment.closestPoints( LineSegment3f( eventLine.p0, eventLine.p1 ), eventClosest ) );
}

private :

float oppositeInspectionValue() const
{
Inspector::ResultPtr oppositeInspection = handleInspection( m_oppositeParameter );
return oppositeInspection ? oppositeInspection->typedValue<float>( 0.f ) : 1.f;
}

V3f edgeToGadgetSpace( const float edge ) const
{
const float scale = m_lightAxis == LightAxis::Width ? m_scale.x : m_scale.y;
return ( ( m_edgeAxis * edge * scale ) / m_edgeToHandleRatio );
return ( ( m_edgeAxis * edge * m_edgeScale ) / m_edgeToHandleRatio );
}

LineSegment3f edgeSegment( const float edgeLength, const float oppositeLength ) const
Expand All @@ -2213,78 +2263,55 @@ class EdgeHandle : public LightToolHandle
float radius0 = 0;
float radius1 = 0;

const float scale = m_lightAxis == LightAxis::Width ? m_scale.y : m_scale.x;
fullEdgeLength = oppositeLength * scale;
fullEdgeLength = oppositeLength * m_oppositeScale;
fullEdgeLengthHalf = fullEdgeLength * 0.5f;

if( m_lightAxis == LightAxis::Width )
{
radius0 = g_circleHandleWidthLarge * ::rasterScaleFactor( this, V3f( 0, -fullEdgeLengthHalf, 0 ) );
radius1 = g_circleHandleWidthLarge * ::rasterScaleFactor( this, V3f( 0, fullEdgeLengthHalf, 0 ) );
}
else
{
radius0 = g_circleHandleWidthLarge * ::rasterScaleFactor( this, V3f( -fullEdgeLengthHalf, 0, 0 ) );
radius1 = g_circleHandleWidthLarge * ::rasterScaleFactor( this, V3f( fullEdgeLengthHalf, 0, 0 ) );
}
radius0 = m_edgeMargin * ::rasterScaleFactor( this, -fullEdgeLengthHalf * m_oppositeAxis );
radius1 = m_edgeMargin * ::rasterScaleFactor( this, fullEdgeLengthHalf * m_oppositeAxis );

LineSegment3f result;

if( m_lightAxis == LightAxis::Width )
{
result.p0 = V3f( 0, std::min( 0.f, -fullEdgeLengthHalf + radius0 ), 0 );
result.p1 = V3f( 0, std::max( 0.f, fullEdgeLengthHalf - radius1 ), 0 );
}
else
{
result.p0 = V3f( std::min( 0.f, -fullEdgeLengthHalf + radius0 ), 0, 0 );
result.p1 = V3f( std::max( 0.f, fullEdgeLengthHalf - radius1 ), 0, 0 );
}
result.p0 = std::min( 0.f, -fullEdgeLengthHalf + radius0 ) * m_oppositeAxis;
result.p1 = std::max( 0.f, fullEdgeLengthHalf - radius1 ) * m_oppositeAxis;

return result;
}

void edgeTransform( const float edgeLength, const LineSegment3f &edgeSegment, M44f &edgeTransform ) const
{
if( m_lightAxis == LightAxis::Width )
{
edgeTransform =
M44f().rotate( V3f( -M_PI * 0.5f, 0, 0 ) ) *
M44f().translate(
V3f( 0, edgeSegment.p0.y, 0 ) + edgeToGadgetSpace( edgeLength )
)
;
}
else
{
edgeTransform =
M44f().rotate( V3f( 0, M_PI * 0.5f, 0 ) ) *
M44f().translate(
V3f( edgeSegment.p0.x, 0, 0 ) + edgeToGadgetSpace( edgeLength )
)
;
}
edgeTransform =
rotationMatrix( V3f( 0, 0, 1.f ), m_oppositeAxis ) *
M44f().translate(
edgeSegment.p0 * m_oppositeAxis + edgeToGadgetSpace( edgeLength )
)
;
}

void coneTransform( const float edgeLength, M44f &coneTransform ) const
{
const V3f gadgetSpaceEdge = edgeToGadgetSpace( edgeLength );
// Rotate the cone 90 degrees around the axis that is the width axis rotated 90 degrees around the z axis.
coneTransform =
M44f().rotate( m_edgeAxis * M44f().rotate( V3f( 0, 0, M_PI * 0.5f ) ) * M_PI * 0.5f ) *
rotationMatrix( V3f( 0, 0, 1.f ), m_edgeAxis ) *
M44f().scale( V3f( ::rasterScaleFactor( this, gadgetSpaceEdge ) ) ) *
M44f().translate( gadgetSpaceEdge )
;
}

const LightAxis m_lightAxis;
const InternedString m_edgeParameter;
const V3f m_edgeAxis;
const float m_edgeToHandleRatio;
const InternedString m_oppositeParameter;
const V3f m_oppositeAxis;
const float m_oppositeToHandleRatio;
V2f m_scale;
const InternedString m_oppositeScaleAttributeName;
const float m_edgeMargin;
const std::string m_tipPlugSuffix;

float m_edgeScale;
float m_oppositeScale;
M44f m_orientation;
float m_oppositeAdditionalScale;
std::optional<LinearDrag> m_drag;
};

Expand Down Expand Up @@ -2994,13 +3021,13 @@ LightTool::LightTool( SceneView *view, const std::string &name ) :

// Quadlight handles

m_handles->addChild( new EdgeHandle( "quad", view, EdgeHandle::LightAxis::Width, "widthParameter", V3f( -1.f, 0, 0 ), 2.f, "heightParameter", V3f( 0, 0, 0 ), 2.f, "westParameter" ) );
m_handles->addChild( new EdgeHandle( "quad", view, "widthParameter", V3f( -1.f, 0, 0 ), 2.f, "heightParameter", V3f( 0, 1.f, 0 ), 2.f, "", g_circleHandleWidthLarge, "widths", "westParameter" ) );
m_handles->addChild( new CornerHandle( "quad", view, "widthParameter", V3f( -1.f, 0, 0 ), 2.f, "heightParameter", V3f( 0, -1.f, 0 ), 2.f, "southWestParameter" ) );
m_handles->addChild( new EdgeHandle( "quad", view, EdgeHandle::LightAxis::Height, "heightParameter", V3f( 0, -1.f, 0 ), 2.f, "widthParameter", V3f( 0, 0, 0 ), 2.f, "southParameter" ) );
m_handles->addChild( new EdgeHandle( "quad", view, "heightParameter", V3f( 0, -1.f, 0 ), 2.f, "widthParameter", V3f( 1.f, 0, 0 ), 2.f, "", g_circleHandleWidthLarge, "heights", "southParameter" ) );
m_handles->addChild( new CornerHandle( "quad", view, "widthParameter", V3f( 1.f, 0, 0 ), 2.f, "heightParameter", V3f( 0, -1.f, 0 ), 2.f, "soutEastParameter" ) );
m_handles->addChild( new EdgeHandle( "quad", view, EdgeHandle::LightAxis::Width, "widthParameter", V3f( 1.f, 0, 0 ), 2.f, "heightParameter", V3f( 0, 0, 0 ), 2.f, "eastParameter" ) );
m_handles->addChild( new EdgeHandle( "quad", view, "widthParameter", V3f( 1.f, 0, 0 ), 2.f, "heightParameter", V3f( 0, 1.f, 0 ), 2.f, "", g_circleHandleWidthLarge, "widths", "eastParameter" ) );
m_handles->addChild( new CornerHandle( "quad", view, "widthParameter", V3f( 1.f, 0, 0 ), 2.f, "heightParameter", V3f( 0, 1.f, 0 ), 2.f, "northEastParameter" ) );
m_handles->addChild( new EdgeHandle( "quad", view, EdgeHandle::LightAxis::Height, "heightParameter", V3f( 0, 1.f, 0 ), 2.f, "widthParameter", V3f( 0, 0, 0 ), 2.f, "northParameter" ) );
m_handles->addChild( new EdgeHandle( "quad", view, "heightParameter", V3f( 0, 1.f, 0 ), 2.f, "widthParameter", V3f( 1.f, 0, 0 ), 2.f, "", g_circleHandleWidthLarge, "heights", "northParameter" ) );
m_handles->addChild( new CornerHandle( "quad", view, "widthParameter", V3f( -1.f, 0, 0 ), 2.f, "heightParameter", V3f( 0, 1.f, 0 ), 2.f, "northWestParameter" ) );

// DiskLight handles
Expand All @@ -3011,6 +3038,10 @@ LightTool::LightTool( SceneView *view, const std::string &name ) :
m_handles->addChild( new RadiusHandle( "point", view, "radiusParameter", 1.f, true, false, "pointHandle" ) );

// CylinderLight handles
m_handles->addChild( new EdgeHandle( "cylinder", view, "radiusParameter", V3f( 0, 1.f, 0 ), 1.f, "lengthParameter", V3f( 0, 0, 1.f ), 2.f, "heightToScaleRatio", 0, "radii", "northRadiusParameter" ) );
m_handles->addChild( new EdgeHandle( "cylinder", view, "radiusParameter", V3f( 1.f, 0, 0 ), 1.f, "lengthParameter", V3f( 0, 0, 1.f ), 2.f, "heightToScaleRatio", 0, "radii", "northRadiusParameter" ) );
m_handles->addChild( new EdgeHandle( "cylinder", view, "radiusParameter", V3f( 0, -1.f, 0 ), 1.f, "lengthParameter", V3f( 0, 0, 1.f ), 2.f, "heightToScaleRatio", 0, "radii", "northRadiusParameter" ) );
m_handles->addChild( new EdgeHandle( "cylinder", view, "radiusParameter", V3f( -1.f, 0, 0 ), 1.f, "lengthParameter", V3f( 0, 0, 1.f ), 2.f, "heightToScaleRatio", 0, "radii", "northRadiusParameter" ) );
m_handles->addChild( new LengthHandle( "cylinder", view, "lengthParameter", V3f( 0, 0, 1.f ), 2.f, "cylinderLengthTop" ) );
m_handles->addChild( new LengthHandle( "cylinder", view, "lengthParameter", V3f( 0, 0, -1.f ), 2.f, "cylinderLengthBottom" ) );

Expand Down
1 change: 1 addition & 0 deletions startup/GafferScene/arnoldLights.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
Gaffer.Metadata.registerValue( "ai:light:cylinder_light", "colorParameter", "color" )
Gaffer.Metadata.registerValue( "ai:light:cylinder_light", "radiusParameter", "radius" )
Gaffer.Metadata.registerValue( "ai:light:cylinder_light", "visualiserOrientation", imath.M44f().rotate( imath.V3f( 0.5 * math.pi, 0 , 0 ) ) )
Gaffer.Metadata.registerValue( "ai:light:cylinder_light", "heightToScaleRatio", 2.0 )

Gaffer.Metadata.registerValue( "ai:light:skydome_light", "intensityParameter", "intensity" )
Gaffer.Metadata.registerValue( "ai:light:skydome_light", "exposureParameter", "exposure" )
Expand Down

0 comments on commit 9d38030

Please sign in to comment.