Authoring Import Patterns

borjaborja Administrator, Fabric Employee Posts: 415 admin
edited February 9 in Tutorials

How to author import patterns?

This document aims to be a guide on creating new or authoring existing import patterns.

Background

Import patterns are just normal canvas graphs which return specific data types. An Import Pattern represents a programmatic pipeline for importing / creating 3D data in supported target applications. Instead of compensating for incomplete / insufficient data pipelines with manual authoring in the target application Import Patterns provide a smart way of improving the pipeline constantly to be able to deal with the source data in a more efficient and complete way.

The relevant data types for import patterns are:

  • ImporterObject (often referred to as an element in this document)
  • ImporterAnimSequence

Import Patterns are also allowed to return arrays of the above data types. The data types are implemented in the GenericImporter extension, which ships with Fabric Engine since version 2.3.1.

Aside from the obvious "Import some data" Import Patterns can also be used to:

  • Filter out unwanted elements from a data set
  • Modify properties of a data set (such as transforms for example)
  • Create or reassign new materials
  • Modify / merge / consolidate shapes and geometries
  • Modify / set metadata on elements (for example to drive collision properties in the target application)
  • Creating completely new procedural elements, including 3D objects, geometries, materials, textures etc.

Getting data in - the file format nodes

Most import patterns start by importing a source asset. The factory nodes for this purpose can be found under Fabric -> Compounds -> IO -> Importer -> File Formats. Third party extensions (such as the OpenNurbs extension for example) might provide the loader nodes in a different folder. In the case of OpenNurbs the loader node can be found under ThirdParty -> OpenNurbsImporter -> OpenNurbs.

Debug drawing - displaying results in real-time

When working on an import pattern it is critical to be able to see what you are doing. For this you can use the drawing nodes which ship with the import patterns extensions. These nodes can be found under Fabric -> Compounds -> IO -> Importer -> Drawing. For most cases you will want to rely on the DrawTraversed node, which is a higher level node that wraps the DrawObjects node.

The DrawTraversed node has a series of features including

  • Drawing in several modes (axes, boxes, shaded, textures)
  • Ability to display several surface colors
  • Single texture channel display
  • Labels for paths, names, ids etc
  • Wireframe and doublesided mode

Filtering elements

Data sets often come with clutter - construction elements or simply unwanted objects. The Filtering nodes for import patterns used Fabric Engine's Blocks feature. This allows you to focus on one element at a time. The base filter node can be found under Fabric -> Compounds -> IO -> Importer -> Filters -> Filter. Based on the default Filter node we also provide a couple pre-canned filter nodes which you can use to filter based on the most common scenarios: Filter by type or path. Using the block on the default Filter node you can implement your very own filtering logic. To make something up: Filter by the original metadata storing the vendor's product name...

Below we see a custom filter based on the name of the object:

Modifying elements

Aside from just filtering out elements you can also use import patterns to actively modify elements. You do this by setting properties on elements - changing properties changes the content of an object. For this you can use the Fabric -> Compounds -> IO -> Importer -> Properties -> SetProperty node. Of course you can use all of the getter nodes in that same category to first retrieve a value and then modify it. With this you can for example:

  • Change the geometry of a shape (polygon decimation for example)
  • Change the transform of an object
  • Change the master of an instance (the element an instance element is referencing)
  • Assign a new material to a shape

Since the Set Property node is polymorphic we'll list here all of the properties you can modify for each specific element. You can also find the properties by looking at the KL source code in the GenericImporter extension. Each specialized ImporterObject adds its very own properties. Note also that you can add custom properties as well. Integrations consuming the results of an import pattern (the Fabric for Maya plugin, for example) might, however, ignore these custom properties.

  • All elements (ImporterObject)

    • visible (Boolean): indicates if an element is visible
    • color (Color): The color of the element - used mainly for debug drawing and identification
  • Elements with transforms (ImporterTransform)

    • localTransform (Mat44): The location transformation of the element
  • Groups (ImporterGroupi)

    • members (String[]): The unique IDs of all members of this group
  • Shapes (ImporterShape)

    • bounds (Box): The local bounds of the shape
    • geometry (Geometry): The geometry of this shape (points, curves or mesh)
    • materials (String[]): The unique IDs of all materials assigned to this shape
    • collisionEnabled (Boolean): indicates if this shape should receive a collision setup in the target application
  • Lights (ImporterLight)

    • color (Color): The color of the light
    • lightEnabled (Boolean): true if this light is turned on
    • lightType (Integer): Type of the light, see the table in ImporterLight.kl in the GenericImporter extension
    • decayType (Integer): Type of decay for the light, see the table in ImporterLight.kl in the GenericImporter extension
    • intensity (Scalar): The intensity of the light - relates to decayType
    • castShadow (Boolean): true if the light is casting a shadow
    • coneAngle (Scalar): the cone angle for this light, only used for spot lights
    • penumbraAngle (Scalar): the penumbra angle for a spot light
    • nearAttenuation (Scalar): the near value of the lights attenuation
    • farAttenuation (Scalar:) the far value of the lights attenuation
  • Instances (ImporterInstance)

    • master (String): The unique ID of the master of this instance (the element this instance is referencing)
  • Cameras (ImporterCamera)

    • focalLength (Scalar): The focal length of the camera in mm
    • fovY (Scalar): The vertical field of view of the camera
    • fStop (Scalar): The aperture of the camera
    • focusDistance (Scalar): The focus distance of the camera in mm
    • near (Scalar): The near clipping distance for the camera
    • far (Scalar): The far clipping distance for the camera
  • Materials (ImporterMaterial)

    • shaderName (String): The name of the shader to use in the target application
    • arbitrary Scalar, Integer, Vec3 and Color properties depending on the material
  • Textures (ImporterTexture)

    • filePath (String) The file path of the texture file referenced
    • swapUV (Boolean) Set to true if the shader should switch U and V texture coordinates for this texture
    • scale (Vec2) The scaling for both U and V texture coordinates
    • translation (Vec2) The offset translation for both U and V texture coordinates
    • rotation (Scalar) The rotation of the UV texture coordinates
    • cropL (Integer) The number of pixels to crop on the left
    • cropR (Integer) The number of pixels to crop on the right
    • cropT (Integer) The number of pixels to crop on the top
    • cropB (Integer) The number of pixels to crop on the bottom

The Fabric -> Compounds -> IO -> Importer -> Blocks -> Modify can be used as a basis for any higher level node that modifies a data set.
The image below shows a modify node changing the transform of each shape by scaling it down:

The image below shows a node setting the collisionEnabled Boolean property, which will be interpreted by Unity and Unreal to drive the collision settings.

Assigning new materials

In the Fabric -> Compounds -> IO -> Importer -> Shapes category you can find the AssignMaterials node. The block inside of the node is used to assign a new material to all of the given shapes in the provided element array. The Fabric -> Compounds -> IO -> Importer -> Importer -> getOrCreatePbsMaterial node can come in handy here. The settings for the physically based shader are used both for Unreal and Unity. This way you can quickly assign materials programmatically which are then reflected well in the target real-time environments.
The image below shows setting up a new material by picking a random color. This can be useful especially when working on geometry decimation / merging.

Merging Meshes

The Fabric -> Compounds -> IO -> Importer -> Shapes -> MergeShapes node can be used to combine multiple shapes. Currently this only supports shapes of type PolygonMesh. To use this node you need to define a key for each element inside of the node's block. The key is used to idenfity the group the shape belongs to. Then all shapes within the same group are merged / combined. So for example:

  • A key which is specific for each object leads to separate shapes
  • A key which is based on the material will cause all objects with the same material to be combined
  • A key which is based on the name might cause all objects with the same name / pattern to be combined

This open approach empowers you to implement the type of merge features you need for your project. See the factory OpenNurbs import pattern for an example.
The image below shows a merge setup where the first five characters of the name are used to define the group. The groups are colored.

Getting and setting MetaData

The nodes inside of Fabric -> Compounds -> IO -> Importer -> MetaData allow you to interact with metadata which might be stored on each element. MetaData doesn't follow a schema, so it might exist or not - depending on the source file. You can however also set metadata to inform the target application or your own process about certain characteristics of an element, for example. Most of the importers will provide specific information, such as the source file's unique identifier per element as metadata.
The image below shows a modify node getting, reporting and setting a specific metadata value, in this case the original name of the material coming from OpenNurbs.

Traversing

The node Fabric -> Compounds -> IO -> Importer -> Blocks -> Traverse can be used to traverse an element array. Traversing means unfolding of hierarchies and creating all of the leaf elements. There are only a few scenarios where this might be needed:

  • The source element array contains unfolded ImporterInstance elements.
  • The source element array contains unfolded ImporterGroup elements.

The Traverse node will create an element for all unfolded hierarchies. So, for example, if an ImporterInstance is referencing a ImporterShape master and we have 4 of these instances we might just have 5 elements (the shape + 4 instances). If you wanted to change the transform on each of 4 resulting cubes you will need to traverse the element array first. After the traverser has run you will result in 9 elements (the cube, 4 instances + 4 instanced cubes). Note that the system is smart about not duplicating heavy data such as the geometry, for example. Only the hierarchical MetaData containers are duplicated.
The DrawTraversed node mentioned in the Drawing Elements section above has the Traverse node built-in. It has a boolean toggle to enable or disable it. Feel free to experiment with the traverser that way and see its effects.

Creating new elements

Aside from just modifying existing elements the import patterns can also create completely new content. Check the following nodes under Fabric -> Compounds -> IO -> Importer -> Importer, namely getOrCreateObject and getOrCreateObjectArray to accomplish this. There are also some convenience nodes for the specific element types, such as getOrCreateLight, getOrCreateCamera etc.
You can create new elements, and then modify their properties as you do with any other element. This can be particularly interesting to create instances of elements procedurally.
Note that the methods used for these nodes are also available in KL. Please see the documentation and the source code of the GenericImporter extension for this.
The image below shows instancing a mesh coming from an alembic source file 10 times.

Animation

Animation is represented as a specific type when building an import pattern. You can use the Fabric -> Compounds -> IO -> Importer -> Animation -> createSequence node for this. The resulting ImporterAnimationSequence can be piped to the output of the graph. Animation sequences contain all of the values for a changing property over time and are imported as native animation clips in the supported environments, such as Unity and Unreal. The most simple case to create an animation sequence is to pipe the results of an animated alembic file into a createSequence node. The transform and camera animation of the elements will become animation tracks in the target application.
The image below shows a very simple setup of driving an animation sequence with all of the content of an alembic source file.

Borja Morales
Technical Product Manager
Fabric Software Inc.

Sign In or Register to comment.