Skip to content

Commit

Permalink
LightPositionTool : Handle multiple selected lights (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericmehl committed Nov 22, 2023
1 parent ef6bade commit 48bc79f
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 2 deletions.
56 changes: 56 additions & 0 deletions python/GafferSceneUITest/LightPositionToolTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

import Gaffer
import GafferUITest
import GafferScene
import GafferSceneUI
import GafferSceneTest

Expand Down Expand Up @@ -99,6 +100,61 @@ def testPosition( self ) :
for j in range( 0, 3 ) :
self.assertAlmostEqual( o[j] % 360, math.degrees( rotationO[j] ) % 360, places = 3 )

def testMultiple( self ) :

script = Gaffer.ScriptNode()

script["group"] = GafferScene.Group()

i = 0
positions = [ imath.V3f( 1, 1, 0 ), imath.V3f( 1, -1, 0 ), imath.V3f( -1, -1, 0 ), imath.V3f( -1, 1, 0 ) ]
for p in positions :
n = "light" + str( i )
script[n] = GafferSceneTest.TestLight()
script[n]["name"].setValue( n )
script[n]["transform"]["translate"].setValue( p )

script["group"]["in"][i].setInput( script[n]["out"] )

i += 1

view = GafferSceneUI.SceneView()
view["in"].setInput( script["group"]["out"] )
GafferSceneUI.ContextAlgo.setSelectedPaths(
view.getContext(),
IECore.PathMatcher( [ "/group/light{}".format( i ) for i in range( 0, 4 ) ] )
)

tool = GafferSceneUI.LightPositionTool( view )
tool["active"].setValue( True )

tool.handlesTransform() # Trigger `updateHandles()` to update our centroid

shadowPivot = imath.V3f( 0, 1, 0 )
shadowPoint = imath.V3f( 0, 0, -1 )
tool.position( shadowPivot, shadowPoint )

transform = imath.M44f().rotate( IECore.degreesToRadians( imath.V3f( -45, 0, 0 ) ) )
transform.translate( self.__shadowSource( imath.V3f( 0 ), shadowPivot, shadowPoint ) )

print( self.__shadowSource( imath.V3f( 0 ), shadowPivot, shadowPoint ) )

i = 0
for p in positions :
newP = script[n]["transform"]["translate"].getValue()
newR = script[n]["transform"]["rotate"].getValue()

self.assertAlmostEqual( newR.x, -45.0, places = 4 )
self.assertAlmostEqual( newR.y, 0.0, places = 4 )
self.assertAlmostEqual( newR.z, 0.0, places = 4 )

desiredP = p * transform
for j in range( 0, 3 ) :
with self.subTest( "Point {}, {} Axis".format( p, {0: "X", 1: "Y", 2: "Z"}.get( j ) ), j=j ) :
self.assertAlmostEqual( newP[j], desiredP[j], places = 4 )

i += 1

def testUndo( self ) :

script = Gaffer.ScriptNode()
Expand Down
22 changes: 20 additions & 2 deletions src/GafferSceneUI/LightPositionTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,14 @@ void LightPositionTool::position( const V3f &shadowPivot, const V3f &shadowPoint
shadowPivot
;

const M44f centroidTransform = rotationMatrix( m_worldCentroid - shadowPivot, newCentroid - shadowPivot );
const M44f centroidPivotFrame = m_centroidOrientation.toMatrix44().translate( m_worldCentroid );

const V3f newDir = ( shadowPivot - newCentroid ).normalized();
const V3f newDirX = newDir.cross( V3f( 0, 1, 0 ) ).normalized();
const V3f newDirY = newDir.cross( newDirX ).normalized();
const M44f newFrame = computeLocalFrame( -newCentroid, newDirX, newDirY );

const M44f centroidTransform = centroidPivotFrame * newFrame.inverse();

UndoScope undoScope( selection().back().editTarget()->ancestor<ScriptNode>() );

Expand Down Expand Up @@ -175,7 +182,18 @@ void LightPositionTool::selectionChanged( const TransformTool &tool )
return;
}

m_worldCentroid = V3f( 0 ) * selection().back().orientedTransform( Orientation::World );
int count = 0;
for( const auto &s : selection() )
{
m_worldCentroid += V3f( 0 ) * s.orientedTransform( Orientation::World );
count ++;
}

m_worldCentroid /= count;

/// \todo Here we're just taking the orientation from the last selected object.
/// Is there a better way?
m_centroidOrientation = extractQuat( selection().back().orientedTransform( Orientation::World ) );
}
}

Expand Down

0 comments on commit 48bc79f

Please sign in to comment.