Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VisualiserTool : Vertex Labels #6212

Open
wants to merge 30 commits into
base: 1.5_maintenance
Choose a base branch
from

Conversation

ericmehl
Copy link
Collaborator

This adds a new method for visualising object data, a vertex label per-vertex.

It uses this new method for vertex indices and integer primitive variables when in Auto mode, leaving the other data types to be displayed as colors. And there's a dedicated Vertex Label mode to see other data types as a label as well. There are some additions that could be made, such as visualising string variables, but I've drawn the line for the PR at the types we support.

This also includes the change from #6190, which I'll close.

Checklist

  • I have read the contribution guidelines.
  • I have updated the documentation, if applicable.
  • I have tested my change(s) in the test suite, and added new test cases where necessary.
  • My code follows the Gaffer project's prevailing coding style and conventions.

@ericmehl ericmehl mentioned this pull request Jan 14, 2025
4 tasks
Copy link
Member

@johnhaddon johnhaddon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Eric - this seems to be working nicely. I've made a few comments about the implementation inline - feel free to ping me when you get in if it's easier to chat about them in person.
Cheers...
John

Comment on lines 258 to 265
menuDefinition.prepend(
"/Vertex Index",
{
"command" : functools.partial( Gaffer.WeakMethod( self.__setDataName ), self.__vertexIndexDataName ),
"checkBox" : self.getPlug().getValue() == self.__vertexIndexDataName,
}
)
menuDefinition.prepend( "/Implicit", { "divider" : True, "label" : "Implicit" } )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess is that Vertex Index will be used less commonly than the various primitive variables, and as the odd one out I think it would make more sense at the bottom of the menu. I'd also suggest using "Other" as the title rather than "Implicit" - it seems a bit more straightforward.

One other note on the menu : it won't show primitive variables from PointsPrimitives, even though we can now draw them. Would be good to get that fixed.

if( layer == Gadget::Layer::MidFront )
{
renderColorVisualiser( viewportGadget );
renderColorVisualiser( viewportGadget, mode );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing the mode to the individual render methods was a surprise to me at first. I was expecting us to resolve "Auto" mode upfront and then only call the single appropriate render method.

I think the reason we're doing it like this instead is so that Auto mode can choose different modes for each object in the selection, when the primvar on those objects is of a different type. Is that right? If so, might be worth a comment.


if( mode == VisualiserTool::Mode::Auto && vData->typeId() == IntVectorDataTypeId )
{
continue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth a comment here I think - "Will be handled by renderVertexLabelValue() instead".

@@ -164,18 +166,19 @@

class _DataNameChooser( GafferUI.PlugValueWidget ) :

__primVarPrefix = "primVar:"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May I suggest "primitiveVariable:" - we don't abbreviate in the other spots we refer to primitive variables.


def __primVarFromDataName( self, name ) :

return name[8:] if name.startswith( self.__primVarPrefix ) else ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems odd to go to the trouble of having __primVarPrefix and then hardcoding the 8.

Comment on lines 1017 to 1044
case FloatVectorDataTypeId :
vData = primitive->expandedVariableData<FloatVectorData>(
primVarName,
IECoreScene::PrimitiveVariable::Vertex,
false /* throwIfInvalid */
);
break;
case V2fVectorDataTypeId :
vData = primitive->expandedVariableData<V2fVectorData>(
primVarName,
IECoreScene::PrimitiveVariable::Vertex,
false /* throwIfInvalid */
);
break;
case V3fVectorDataTypeId :
vData = primitive->expandedVariableData<V3fVectorData>(
primVarName,
IECoreScene::PrimitiveVariable::Vertex,
false /* throwIfInvalid */
);
break;
case Color3fVectorDataTypeId :
vData = primitive->expandedVariableData<Color3fVectorData>(
primVarName,
IECoreScene::PrimitiveVariable::Vertex,
false /* throwIfInvalid */
);
break;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems rather longwinded when you consider that vData is just a ConstDataPtr, so we've thrown away all the type information we got from the templated calls to expandedVariableData(). Can we just use one expandedVariableData<Data>() call after checking the types more concisely?

Comment on lines +1289 to +1305
if( auto fData = runTimeCast<const FloatVectorData>( vData.get() ) )
{
auto data = runTimeCast<FloatData>( vertexValue );
if( !data )
{
data.reset( new FloatData() );
}
data->writable() = fData->readable()[i];
vertexValue = data;
}
if( auto v2fData = runTimeCast<const V2fVectorData>( vData.get() ) )
{
auto data = runTimeCast<V2fData>( vertexValue );
if( !data )
{
data.reset( new V2fData() );
}
data->writable() = v2fData->readable()[i];
vertexValue = data;
}
if( auto v3fData = runTimeCast<const V3fVectorData>( vData.get() ) )
{
auto data = runTimeCast<V3fData>( vertexValue );
if( !data )
{
data.reset( new V3fData() );
}
data->writable() = v3fData->readable()[i];
vertexValue = data;
}
if( auto c3fData = runTimeCast<const Color3fVectorData>( vData.get() ) )
{
auto data = runTimeCast<Color3fData>( vertexValue );
if( !data )
{
data.reset( new Color3fData() );
}
data->writable() = c3fData->readable()[i];
vertexValue = data;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we going to all this trouble of making an intermediate per-vertex Data value? Why don't we just format to a string directly here?

Comment on lines 110 to 119
"preset:Color (Type Range)", GafferSceneUI.VisualiserTool.Mode.ColorTypeRange,
"preset:Color (Manual Range)", GafferSceneUI.VisualiserTool.Mode.ColorManualRange,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you're trying to convey the underlying mechanism in the name here, but I do wonder if maybe "Type Range" is a bit unobvious? I think maybe "Auto Range" conveys more quickly that the range will be picked for you, and then the tooltip can tell you the details of how.

Maybe just "Color" and "Color (Auto Range)" for the names?

I'm bikeshedding here, and others may disagree, so feel free to canvas other opinions.

drawStrokedText(
viewportGadget,
text,
m_tool->sizePlug()->getValue(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect it's worth lifting sizePlug()->getValue() out of the per-vertex loop.

cursorVertexRasterPos.y
),
style,
Style::State::HighlightedState
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm finding the blue text for the hovered vertex value to be less readable than the white. I think perhaps the size change is enough on its own.

This is in preparation for visualising vertex indices. By namespacing
primitive variable names, we can ensure there are no collisions between
special data names (for things like vertex indices) and primitive
variable names.
Timing the previous `stringstream` implementation vs `fmt::format` shows
about a 70% speedup for formatting a sample mesh's vertex indices.
@ericmehl
Copy link
Collaborator Author

I think I have the comments addressed except for the drag-value-shared-data part. Hold off just a bit on reviewing the fixups so I can take a fresh look on Monday and we can talk through the data handling part then too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants