Skip to content

Commit

Permalink
MergeObjects : Add base class.
Browse files Browse the repository at this point in the history
  • Loading branch information
danieldresser-ie committed Aug 2, 2024
1 parent e45e9ae commit a4b3be2
Show file tree
Hide file tree
Showing 6 changed files with 1,693 additions and 0 deletions.
145 changes: 145 additions & 0 deletions include/GafferScene/MergeObjects.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
//////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2024, Image Engine Design Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above
// copyright notice, this list of conditions and the following
// disclaimer.
//
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided with
// the distribution.
//
// * Neither the name of John Haddon nor the names of
// any other contributors to this software may be used to endorse or
// promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#pragma once

#include "GafferScene/FilteredSceneProcessor.h"

#include "Gaffer/TypedObjectPlug.h"

#include "IECore/CompoundData.h"

namespace Gaffer
{

IE_CORE_FORWARDDECLARE( StringPlug )

} // namespace Gaffer

namespace GafferScene
{

/// A base class for scene nodes that merge locations into combined
/// locations. Appropriate for nodes which merge primitives, or convert
/// transforms to points.
///
/// More complicated then you would expect, because it supports arbitrary
/// many-to-many remapping across the hierarchy. `destination` may depend
/// on `scene:path` to give a unique destination to each filtered source.
/// All source locations are merged into their corresponding destination
/// locations, creating the destination if it doesn't exist already. Then
/// all source locations that are not also a destination are pruned.
///
/// Derived classe just need to implement `mergeObjects()` to do the actual
/// merge.
class GAFFERSCENE_API MergeObjects : public FilteredSceneProcessor
{

public :

~MergeObjects() override;

GAFFER_NODE_DECLARE_TYPE( GafferScene::MergeObjects, MergeObjectsTypeId, FilteredSceneProcessor );

GafferScene::ScenePlug *sourcePlug();
const GafferScene::ScenePlug *sourcePlug() const;

Gaffer::StringPlug *destinationPlug();
const Gaffer::StringPlug *destinationPlug() const;

void affects( const Gaffer::Plug *input, AffectedPlugsContainer &outputs ) const override;

protected :

explicit MergeObjects( const std::string &name=defaultName<MergeObjects>() );

void hash( const Gaffer::ValuePlug *output, const Gaffer::Context *context, IECore::MurmurHash &h ) const override;
void compute( Gaffer::ValuePlug *output, const Gaffer::Context *context ) const override;

void hashBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const override;
void hashTransform( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const override;
void hashAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const override;
void hashObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const override;
void hashChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const override;
void hashSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const override;

Imath::Box3f computeBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const override;
Imath::M44f computeTransform( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const override;
IECore::ConstCompoundObjectPtr computeAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const override;
IECore::ConstObjectPtr computeObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const override;
IECore::ConstInternedStringVectorDataPtr computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const override;
IECore::ConstPathMatcherDataPtr computeSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent ) const override;

Gaffer::ValuePlug::CachePolicy hashCachePolicy( const Gaffer::ValuePlug *output ) const override;
Gaffer::ValuePlug::CachePolicy computeCachePolicy( const Gaffer::ValuePlug *output ) const override;


/// @name Actual object merge function
/// This must be implemented by derived classes. It receives a vector of pairs of objects
/// and their transforms.
///
virtual IECore::ConstObjectPtr mergeObjects(
const std::vector< std::pair< IECore::ConstObjectPtr, Imath::M44f > > &sourcePaths,
const Gaffer::Context *context
) const = 0;

// \todo - should we offer alternate ways to merge bounds? Can we think of any use cases for this?
//virtual Imath::Box3f mergeBounds( const std::vector< ScenePath > &sourcePaths, const Gaffer::Context *context ) const;

protected:

/// The source plug currently being used for merge sources - will be `source` if connected, otherwise
/// `in`.
const GafferScene::ScenePlug *effectiveSourcePlug() const;

private :

/// The tree holds all destinations, with their corresponding sources.
Gaffer::ObjectPlug *treePlug();
const Gaffer::ObjectPlug *treePlug() const;

/// The mergeLocation data gives the resulting child names for each location, together with which
/// sources are needed to evaluate the child locations.
Gaffer::ObjectPlug *mergeLocationPlug();
const Gaffer::ObjectPlug *mergeLocationPlug() const;

static size_t g_firstPlugIndex;

};

IE_CORE_DECLAREPTR( MergeObjects )

} // namespace GafferScene
1 change: 1 addition & 0 deletions include/GafferScene/TypeIds.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ enum TypeId
MeshTessellateTypeId = 110639,
RenderPassShaderTypeId = 110640,
ShaderTweakProxyTypeId = 110641,
MergeObjectsTypeId = 110642,

PreviewPlaceholderTypeId = 110647,
PreviewGeometryTypeId = 110648,
Expand Down
96 changes: 96 additions & 0 deletions python/GafferSceneUI/MergeObjectsUI.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
##########################################################################
#
# Copyright (c) 2024, Image Engine Design Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided with
# the distribution.
#
# * Neither the name of John Haddon nor the names of
# any other contributors to this software may be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

import IECore

import Gaffer
import GafferUI

import GafferScene
import GafferSceneUI

##########################################################################
# Metadata
##########################################################################

Gaffer.Metadata.registerNode(

GafferScene.MergeObjects,

"description",
"""
The base type for scene nodes that merge locations into combined
locations. Appropriate for nodes which merge primitives, or convert
transforms to points.
""",

plugs = {

"destination" : [

"description",
"""
The destination location where filtered locations will be merged to. The destination
location will be created if it doesn't exist already. If the name overlaps with an existing
location that isn't filtered, the name will get a suffix. May depend on the current value
of scene:path in order to individually map input locations to different destinations.
""",

],

"filter" : [

"description",
"""
The filter used to control which parts of the scene are
processed. A Filter node should be connected here.
Any filtered locations which aren't used as part of a destination will be pruned.
"""
],

"source" : [

"description",
"""
If connected, this scene will provide the sources for the merge, and the `in` scene
will be preserved except for the newly added merge locations.
"""

]

},

)
1 change: 1 addition & 0 deletions python/GafferSceneUI/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@
from . import MeshTessellateUI
from . import RenderPassTypeAdaptorUI
from . import RenderPassShaderUI
from . import MergeObjectsUI

# then all the PathPreviewWidgets. note that the order
# of import controls the order of display.
Expand Down
Loading

0 comments on commit a4b3be2

Please sign in to comment.