Skip to content

Commit

Permalink
Version 2.0.54 - Houdini 18.5.759
Browse files Browse the repository at this point in the history
Update 5 of the V2 Plugin.
The plug-in is now linked to Houdini 18.5.759 / HAPI 3.7.3.

As H18.5.759 is the last 18.5 production, this release will be the last update for the v2 plugin for H18.5.

The Houdini 19.0 plugin can be found in the Houdini Engine for UYnreal repository
https://github.com/sideeffects/HoudiniEngineForUnreal



New Features:

Added support for controlling Nanite settings via attributes (UE5)
"unreal_nanite_enabled" (int, 0 or 1 ) can be used to enable Nanite processing when building a StaticMesh.
"unreal_nanite_position_precision" (int) can be used to set the position precision. Step size is 2^(-Value) cm
"unreal_nanite_percent_triangles" (float [0 1]) can be used to control the percentage of triangles to keep from LOD0. 1.0 = no reduction, 0.0 = no triangles.

Added support for generating landscapes with edit layers
By using the "Generate" output mode, (unreal_landscape_output_mode set to 0).
Edit layer attributes arte now supported on heightfield primitives.

It is now possible to set the default directory used in the browse dialog for File parameters by using the "default_dir" Parameter tag.

By default, the plugin now uses the output nodes found in a HDA instead of the display flag.

For landscape inputs, the option to marshall only selected landscapes was added, as well as the auto-selection of landscape component using the asset bounds.
(those two features existed previously in the v1 plugin)
Added an "Update selected components" button, that updates the selected components to the current landscape selection.

Added a new attribute, "unreal_force_instancer", that can be used to ensure that an instancer component is created even if there is only a single instance of a StaticMesh.
If unreal_foliage, unreal_split_instances or unreal_hierarchical_instancer is set and not 0, then the particular instancer type is created even if there is only a single instance of the StaticMesh.

Added support for the "unreal_bake_name" attribute that can be used to set the name of the object(s) generated during baking. The "unreal_output_name" attribute takes precedence.
When baking Houdini Instanced Actor Components the "unreal_output_name" (or "unreal_bake_name") attribute, if set, is now used to determine the baked instance actor names.
When baking Houdini Instanced Actor Components the instanced object name is now used as the default bake name instead of the HDA actor's name (if the "unreal_output_name" and unreal_bake_name attributes are not set).
Houdini Instanced Actor Components now support the "unreal_bake_actor" attribute when baking: the instanced actors are attached to unreal_bake_actor (which is created as an empty actor or re-used from a previous bake depending on the replacement mode).


Bugs Fixes:

- Fixed Wrong tooltip on Landscape Input "Update Landscape Data"
- UE5: Fixed "double cooking" issue when instantiating a new HDA by dragging it on the viewport. Like in UE4, the HDA is only cooked after being dropped.
- Fixed a regression that caused rebuilds to fail with "Fatal error - invalid".
- All UHoudiniPublicAPIInput classes are now API exported in the C++ Public API.
- AHoudiniAssetActor is now public in the C++ API.
- Fixed setting multiparm parameters via the Public API.
- Fixed various issues with Modify landscape output mode.
- Fixed an issue where temporary landscapes were not spawned in the HAC's level.
- Fixed an issue where HDA would output from hidden or nested subnets.
- Fixed handling of output data between Display nodes and Output nodes to match Houdini's internal behaviour.
- Fixed a material update issue for tiled landscapes.
- Fixed an issue where input updates/changes via the public API, especially with curve inputs, would not always take effect.
- Fixed loading of PDG output regression.
- UE5: Fixed an issue where bake to actor would fail and not create any baked actors / assets.
- Fixed a crash when trying to assign object path properties via generic attributes with an invalid path.
- Fixed unreal_landscape_editlayer_target attribute for Landscape Modify mode.
- Fixed landscape input targeting using Input0, Input1, etc.
- Fixed Landscape edit layer transforms in Modify mode.
- Fixed an issue where HDA would fail to produce an output if the HDA is a SOP/Subnet with the display flag set on an output node, and the "Use Output Nodes is enabled" option is enabled.
- Houdini to Unreal StaticMesh translation: fixed an issue where duplicate warnings would be logged in Unreal for meshes with invalid face / vertex data, for each invalid index.
- Fixed landscape tile resizing in Generate mode.
- Fixed an issue where nested empty folders might crash Unreal or Houdini Engine
- Fixed output updates / HDA cooking issues that can occur when using Session Sync.
- Fixed an issue during baking where the baked actors of the work items of a TOP node in the PDG asset link were not shared with the remaining work items on the TOP node.
- Fixed an issue when processing a spline/curve from Houdini where attributes such as "unreal_output_name" and "unreal_bake_actor" were not always updated when the HDA was cooked more than once, resulting in baking producing incorrect output names / bake actor names.
If unreal_bake_actor is not set for a spline / curve we now use "unreal_output_name" to determine the bake actor name.
- Improved how work items of TOP nodes are associated with previous cook / bake data in the PDG asset link.
- Fixed various cases where after a successful bake the plug-in incorrectly reported that 0 packages were created and/or updated.
- Fixed an issue where the HDA wouldn't properly switch between editable and non-editable curve.
- Fixed cleanup issue of Houdini Spline input objects in Houdini sessions.
- Fixed an issue where data tables with invalid names (spaces or colons) would not marshall data into Houdini Engine.
- The generated mesh output now properly uses the collision complexity from the Houdini Mesh Generation Properties. A side effect of this is that the default collision complexity behaviour is now CTF_UseDefault instead of CTF_UseComplexAsSimple.
- Fixed issues regarding exported input capsule colliders with rotations.
- Fixed issues regarding exported input translation/rotation/scale of convex collider collisions.
- Updated how the plugin tries to detect if an HDA should have a PDGAssetLink created. The plugin now simply looks for non scheduler/non bypassed TOP nodes in the asset. Previously it would look for TOP nodes inside all the non bypassed TOP/SOP network, which in some case drastically increased the HDA instantiation time, even for assets without any TOP nodes.
- A Landscape's visibility layer is now properly named when sent as heightfield data to Houdini.
- Fixed an issue where collision presets were not being saved from the plugin settings
- When removing temporary PDG outputs the plugin now also uses the HoudiniAssetComponent's GUID in the package metadata to determine if the output asset may be deleted.
- Fixed BSP transform issue.
- Fixed an issue where nodes for world input actors were always recreated on update
- Fixed an issue where landscape input transform changes were not applied correctly
- Fixed an issue with output node: the plugin now ensures that all data from all output nodes are being output properly.
- Prevent modifying non-editlayer landscapes when using the Modify Layer output mode.
- Fixed tracking of transform changes, as well as transform uploading issues, of non-root components in World Input objects.
- Fixed transform updating for Spline components
- Fixed an issue where input nodes were not cleaned up in the session.
- Prevent cooking of HDAs during PIE except for HDAs that are refining geometry.
  We now make sure that the plugin is inactive / not ticking during PIE after refinement is completed.
  • Loading branch information
dpernuit committed Nov 17, 2021
1 parent dc50314 commit d7c3892
Show file tree
Hide file tree
Showing 103 changed files with 6,945 additions and 2,619 deletions.
5 changes: 4 additions & 1 deletion Content/Examples/Cpp/CurveInputExample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "Examples/CurveInputExample.h"
#include "CurveInputExample.h"

#include "Engine/StaticMesh.h"

#include "HoudiniAsset.h"
#include "HoudiniPublicAPI.h"
#include "HoudiniPublicAPIBlueprintLib.h"
#include "HoudiniPublicAPIAssetWrapper.h"
Expand Down
2 changes: 1 addition & 1 deletion Content/Examples/Cpp/CurveInputExample.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
class UHoudiniPublicAPIAssetWrapper;

UCLASS()
class HOUDINIENGINEEDITOR_API ACurveInputExample : public AEditorUtilityActor
class ACurveInputExample : public AEditorUtilityActor
{
GENERATED_BODY()

Expand Down
128 changes: 128 additions & 0 deletions Content/Examples/Cpp/IterateOverHoudiniActorsExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright (c) <2021> Side Effects Software 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:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. The name of Side Effects Software may not be used to endorse or
* promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE "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 SIDE EFFECTS SOFTWARE 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.
*/


#include "IterateOverHoudiniActorsExample.h"

#include "EngineUtils.h"

#include "HoudiniAssetActor.h"
#include "HoudiniPublicAPI.h"
#include "HoudiniPublicAPIBlueprintLib.h"
#include "HoudiniPublicAPIAssetWrapper.h"


// Sets default values
AIterateOverHoudiniActorsExample::AIterateOverHoudiniActorsExample()
{
}

void AIterateOverHoudiniActorsExample::RunIterateOverHoudiniActorsExample_Implementation()
{
// Get the API instance
UHoudiniPublicAPI* const API = UHoudiniPublicAPIBlueprintLib::GetAPI();
// Ensure we have a running Houdini Engine session
if (!API->IsSessionValid())
API->CreateSession();

// Iterate over HoudiniAssetActors in the world (by default when instantiating an HDA in the world an
// AHoudiniAssetActor is spawned, which has a component that manages the instantiated HDA node in Houdini Engine.
UWorld* const OurWorld = GetWorld();
for (TActorIterator<AHoudiniAssetActor> It(OurWorld); It; ++It)
{
AHoudiniAssetActor* const HDAActor = *It;
if (!IsValid(HDAActor))
continue;

// Print the name of the actor
UE_LOG(LogTemp, Display, TEXT("HDA Actor (Name, Label): %s, %s"), *(HDAActor->GetName()), *(HDAActor->GetActorLabel()));

// Wrap it with the API
UHoudiniPublicAPIAssetWrapper* const Wrapper = UHoudiniPublicAPIAssetWrapper::CreateWrapper(this, HDAActor);
if (!IsValid(Wrapper))
continue;

// Print its parameters via the API
TMap<FName, FHoudiniParameterTuple> ParameterTuples;
if (!Wrapper->GetParameterTuples(ParameterTuples))
{
// The operation failed, log the error
FString ErrorMessage;
if (Wrapper->GetLastErrorMessage(ErrorMessage))
UE_LOG(LogTemp, Warning, TEXT("%s"), *ErrorMessage);

continue;
}

UE_LOG(LogTemp, Display, TEXT("# Parameter Tuples: %d"), ParameterTuples.Num());
for (const auto& Entry : ParameterTuples)
{
UE_LOG(LogTemp, Display, TEXT("\tParameter Tuple Name: %s"), *(Entry.Key.ToString()));

const FHoudiniParameterTuple& ParameterTuple = Entry.Value;
TArray<FString> Strings;
FString Type;
if (ParameterTuple.BoolValues.Num() > 0)
{
Type = TEXT("Bool");
for (const bool Value : ParameterTuple.BoolValues)
{
Strings.Add(Value ? TEXT("1") : TEXT("0"));
}
}
else if (ParameterTuple.FloatValues.Num() > 0)
{
Type = TEXT("Float");
for (const float Value : ParameterTuple.FloatValues)
{
Strings.Add(FString::Printf(TEXT("%.4f"), Value));
}
}
else if (ParameterTuple.Int32Values.Num() > 0)
{
Type = TEXT("Int32");
for (const int32 Value : ParameterTuple.Int32Values)
{
Strings.Add(FString::Printf(TEXT("%d"), Value));
}
}
else if (ParameterTuple.StringValues.Num() > 0)
{
Type = TEXT("String");
Strings = ParameterTuple.StringValues;
}

if (Type.Len() == 0)
{
UE_LOG(LogTemp, Display, TEXT("\t\tEmpty"));
}
else
{
UE_LOG(LogTemp, Display, TEXT("\t\t%s Values: %s"), *Type, *FString::Join(Strings, TEXT("; ")));
}
}
}
}
45 changes: 45 additions & 0 deletions Content/Examples/Cpp/IterateOverHoudiniActorsExample.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) <2021> Side Effects Software 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:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. The name of Side Effects Software may not be used to endorse or
* promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE "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 SIDE EFFECTS SOFTWARE 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 "CoreMinimal.h"
#include "EditorUtilityActor.h"

#include "IterateOverHoudiniActorsExample.generated.h"

UCLASS()
class APIEXAMPLEEDITOR_API AIterateOverHoudiniActorsExample : public AEditorUtilityActor
{
GENERATED_BODY()

public:
// Sets default values for this actor's properties
AIterateOverHoudiniActorsExample();

UFUNCTION(BlueprintNativeEvent, BlueprintCallable, CallInEditor)
void RunIterateOverHoudiniActorsExample();
};
24 changes: 15 additions & 9 deletions Content/Examples/Python/eau_curve_input_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@

@unreal.uclass()
class CurveInputExample(unreal.PlacedEditorUtilityBase):
def __init__(self, *args, **kwargs):
self._asset_wrapper = None
# Use a FProperty to hold the reference to the API wrapper we create in
# run_curve_input_example
_asset_wrapper = unreal.uproperty(unreal.HoudiniPublicAPIAssetWrapper)

@unreal.ufunction(meta=dict(BlueprintCallable=True, CallInEditor=True))
def run_curve_input_example(self):
# Get the API instance
api = unreal.HoudiniPublicAPIBlueprintLib.get_api()
Expand All @@ -40,15 +42,17 @@ def run_curve_input_example(self):
# Load our HDA uasset
example_hda = unreal.load_object(None, '/HoudiniEngine/Examples/hda/copy_to_curve_1_0.copy_to_curve_1_0')
# Create an API wrapper instance for instantiating the HDA and interacting with it
self._asset_wrapper = api.instantiate_asset(example_hda, instantiate_at=unreal.Transform())
if self._asset_wrapper:
wrapper = api.instantiate_asset(example_hda, instantiate_at=unreal.Transform())
if wrapper:
# Pre-instantiation is the earliest point where we can set parameter values
self._asset_wrapper.on_pre_instantiation_delegate.add_callable(self._set_initial_parameter_values)
wrapper.on_pre_instantiation_delegate.add_function(self, '_set_initial_parameter_values')
# Jumping ahead a bit: we also want to configure inputs, but inputs are only available after instantiation
self._asset_wrapper.on_post_instantiation_delegate.add_callable(self._set_inputs)
wrapper.on_post_instantiation_delegate.add_function(self, '_set_inputs')
# Jumping ahead a bit: we also want to print the outputs after the node has cook and the plug-in has processed the output
self._asset_wrapper.on_post_processing_delegate.add_callable(self._print_outputs)
wrapper.on_post_processing_delegate.add_function(self, '_print_outputs')
self.set_editor_property('_asset_wrapper', wrapper)

@unreal.ufunction(params=[unreal.HoudiniPublicAPIAssetWrapper], meta=dict(CallInEditor=True))
def _set_initial_parameter_values(self, in_wrapper):
""" Set our initial parameter values: disable upvectorstart and set the scale to 0.2. """
# Uncheck the upvectoratstart parameter
Expand All @@ -58,8 +62,9 @@ def _set_initial_parameter_values(self, in_wrapper):
in_wrapper.set_float_parameter_value('scale', 0.2)

# Since we are done with setting the initial values, we can unbind from the delegate
in_wrapper.on_pre_instantiation_delegate.remove_callable(self._set_initial_parameter_values)
in_wrapper.on_pre_instantiation_delegate.remove_function(self, '_set_initial_parameter_values')

@unreal.ufunction(params=[unreal.HoudiniPublicAPIAssetWrapper], meta=dict(CallInEditor=True))
def _set_inputs(self, in_wrapper):
""" Configure our inputs: input 0 is a cube and input 1 a helix. """
# Create an empty geometry input
Expand Down Expand Up @@ -94,8 +99,9 @@ def _set_inputs(self, in_wrapper):
in_wrapper.set_input_at_index(1, curve_input)

# unbind from the delegate, since we are done with setting inputs
in_wrapper.on_post_instantiation_delegate.remove_callable(self._set_inputs)
in_wrapper.on_post_instantiation_delegate.remove_function(self, '_set_inputs')

@unreal.ufunction(params=[unreal.HoudiniPublicAPIAssetWrapper], meta=dict(CallInEditor=True))
def _print_outputs(self, in_wrapper):
""" Print the outputs that were generated by the HDA (after a cook) """
num_outputs = in_wrapper.get_num_outputs()
Expand Down
103 changes: 103 additions & 0 deletions Content/Examples/Python/iterate_over_houdini_asset_actors_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Copyright (c) <2021> Side Effects Software 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:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. The name of Side Effects Software may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE "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 SIDE EFFECTS SOFTWARE 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.


""" Example script that uses unreal.ActorIterator to iterate over all
HoudiniAssetActors in the editor world, creates API wrappers for them, and
logs all of their parameter tuples.
"""

import unreal


def run():
# Get the API instance
api = unreal.HoudiniPublicAPIBlueprintLib.get_api()

# Get the editor world
editor_subsystem = None
world = None
try:
# In UE5 unreal.EditorLevelLibrary.get_editor_world is deprecated and
# unreal.UnrealEditorSubsystem.get_editor_world is the replacement,
# but unreal.UnrealEditorSubsystem does not exist in UE4
editor_subsystem = unreal.UnrealEditorSubsystem()
except AttributeError:
world = unreal.EditorLevelLibrary.get_editor_world()
else:
world = editor_subsystem.get_editor_world()

# Iterate over all Houdini Asset Actors in the editor world
for houdini_actor in unreal.ActorIterator(world, unreal.HoudiniAssetActor):
if not houdini_actor:
continue

# Print the name and label of the actor
actor_name = houdini_actor.get_name()
actor_label = houdini_actor.get_actor_label()
print(f'HDA Actor (Name, Label): {actor_name}, {actor_label}')

# Wrap the Houdini asset actor with the API
wrapper = unreal.HoudiniPublicAPIAssetWrapper.create_wrapper(world, houdini_actor)
if not wrapper:
continue

# Get all parameter tuples of the HDA
parameter_tuples = wrapper.get_parameter_tuples()
if parameter_tuples is None:
# The operation failed, log the error message
error_message = wrapper.get_last_error_message()
if error_message is not None:
print(error_message)

continue

print(f'# Parameter Tuples: {len(parameter_tuples)}')
for name, data in parameter_tuples.items():
print(f'\tParameter Tuple Name: {name}')

type_name = None
values = None
if data.bool_values:
type_name = 'Bool'
values = '; '.join(('1' if v else '0' for v in data.bool_values))
elif data.float_values:
type_name = 'Float'
values = '; '.join((f'{v:.4f}' for v in data.float_values))
elif data.int32_values:
type_name = 'Int32'
values = '; '.join((f'{v:d}' for v in data.int32_values))
elif data.string_values:
type_name = 'String'
values = '; '.join(data.string_values)

if not type_name:
print('\t\tEmpty')
else:
print(f'\t\t{type_name} Values: {values}')


if __name__ == '__main__':
run()
4 changes: 2 additions & 2 deletions HoudiniEngine.uplugin
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"FileVersion" : 3,
"FriendlyName" : "Houdini Engine v2",
"Version" : 18050696,
"VersionName" : "v2.0 - H18.5.696",
"Version" : 18050759,
"VersionName" : "v2.0 - H18.5.759",
"CreatedBy" : "Side Effects Software Inc.",
"CreatedByURL" : "http://www.sidefx.com",
"DocsURL" : "http://www.sidefx.com/docs/unreal/",
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

Welcome to the repository for Version 2 of the Houdini Engine For Unreal Plugin.

** As only version 2 of the plugin now ships with Houdini 19.0, regular updates of the version 2 plugin now happen on the [HoudiniEngineForUnreal](https://github.com/sideeffects/HoudiniEngineForUnreal) repository. The source code available on this repository is only for Houdini 18.5, and will stop to recieve updates after the last Houdini 18.5 production build. **

This plug-in brings Houdini's powerful and flexible procedural workflow into Unreal Engine through Houdini Digital Assets. Artists can interactively adjust asset parameters inside the editor and use Unreal assets as inputs. Houdini's procedural engine will then "cook" the asset and the results will be available in the editor without the need for baking.

Version 2 is a significant rewrite of the core architecture of the existing Houdini Engine plugin, and comes  with many new features, and improvements.
Expand Down
Loading

0 comments on commit d7c3892

Please sign in to comment.