Updated Objects
Many objects are updated to meet the needs of the higher quality renderers and to increase the pipeline interoperability with other DCC tools.
Lights
The light models now include more features such as, animatable barn door properties, spot light type includes inner and outer cone settings to create penumbra, and area light type (rectangle and sphere shapes) are available for soft shadow. The FBX file format can transfer these properties seamlessly to Maya and other DCC tools. The new light types and properties are shown in the following figure.
To enable the UI widgets setting for these new lighting properties, you need to turn on the FBRenderer::AdvancedLightingMode
upon custom renderer object creation, or permanently by using Rendering
AdvancedLightinUISetting
preference in the configuration file.
bool ORCustomRendererCallback::FBCreate()
{
…
// Enabled advanced lighting mode, include UI widgets for various advanced lighting
// setting, includes:
// Light: area light, spot light inner/outer angles, barn doors, and others.
// Model: PrimaryVisibility, CastsShadows, and ReceiveShadows.
FBSystem::TheOne().Renderer->AdvancedLightingMode = true;
Currently, the default renderer does not use these new properties for viewport rendering.
You can subclass FBLight
to provide custom rig display in the viewport and add additional properties. You can use the FBX file format to store and retrieve the custom light types. It uses a similar extension mechanism like the custom marker type. For example, see
Models
Three new properties are added to the models: Primary Visibility, Casts Shadows, and Receive Shadows. The custom renderer uses these properties to access the shadow setting for each model and align with other DCC tools. The following figure shows these properties for the Model object.
To view these new properties in the property editor, you need to turn on the AdvancedLightingMode
(see the Lights section). You can also subclass FBModel
to create a custom model type. For example, see
Geometry
MotionBuilder supports the mesh, nurbs, and patch type surfaces (FBMesh
, FBNurbs
, and FBPatch
). For rendering performance and implementation simplicity, all the surface types are tessellated into a triangle list. Depending on the material, texture mapping relationships, and other vertex attributes, some vertexes might be duplicated. The resulting vertex arrays take part in the skinning (if necessary) and rendering procedures.
You can access FBModel::Geometry
for the original geometry, FBModel::TessellatedMesh
for the tessellated mesh, and FBModel::ModelVertexData
for the final rendering ready geometry.
You can use a set of new API functions for fast mesh creation and editing by directly manipulating the vertex (position, normal, tangent, binormal, and UV) and polygon index (material mapping) arrays. Similar APIs exist both in the ORSDK and Python layers. For example, see
It is a best practice to combine the static background entities into a single model to reduce runtime overhead and save memory. Refer to the following sections for more information on how you can use the APIs to implement this optimization procedure in your workflow and pipeline.
Instancing
MotionBuilder supports geometry instancing that can save memory and IO time significantly. In the viewport, simply select a model, copy, and then paste it. By performing this action, you are actually creating a new model instance that shares the same geometry instancing with the source model.
It is easy to instance geometry by using the SDK. For example, see
Deformation
MotionBuilder supports different deformation techniques such as, skinning, blendshape, and point cache. The deformation evaluation tasks are either executed in the background threads of the CPU cores concurrently, or at the beginning of the rendering pipeline using a powerful GPU (for skinning and blendshape types). To enable the GPU deformation, you need a CUDA™ enabled video card installed. You can use the configurable shortcut (press Ctrl+Shift+T) or preference (Display
UseGPUSkinDeform
) to toggle globally. Depending on the hardware used for deployment, the overall evaluation and rendering performance for the same scene might vary.
The following Python script shows how to create multiple cluster skinning meshes.
from pyfbsdk import *
def CreateDeformQuad():
lModel = FBModelCube("myMesh");
# Create a mesh and replace the mesh on the FBModelCube
lGeom = FBMesh("myMesh")
# use GeometryBegin()/GeometryEnd() to enclose geometry editing code.
lGeom.GeometryBegin()
lModel.Geometry = lGeom
lGeom.VertexInit(0, False);
lV1 = lGeom.VertexAdd(-10.0, -10.0, -10.0)
lV2 = lGeom.VertexAdd(-10.0, -10.0, 10.0)
lV3 = lGeom.VertexAdd(10.0, -10.0, 10.0)
lGeom.PolygonBegin(0)
lGeom.PolygonVertexAdd(lV1);
lGeom.PolygonVertexAdd(lV2);
lGeom.PolygonVertexAdd(lV3);
lGeom.PolygonEnd()
lGeom.GeometryEnd()
lBone = FBModelCube("myBone")
skinCluster = FBCluster(lModel)
# use ClusterBegin()/ClusterEnd() to enclose weigh editing code.
skinCluster.ClusterBegin(0)
skinCluster.VertexAdd(lV1, 1.0)
skinCluster.VertexAdd(lV2, 1.0)
skinCluster.VertexAdd(lV3, 1.0)
skinCluster.LinkSetModel(lBone)
skinCluster.ClusterEnd()
lModel.Show = True
lBone.Show = True
for i in range(0, 3):
CreateDeformQuad()
For creating blendshape deformation, see
You can also extend the custom constraint deformer if a different deformation method is required. For implementation details, see the sample in
Vertex Buffer Object
You need to use an instance of the FBModelVertexData
class through the FBModel::ModelVertexData
property to access the rendering ready geometry data in the OpenGL vertex buffer object (VBO) format.
A single geometry might have multiple regions and each region can be mapped with different material. Each region can have several patches and each patch might have different primitive types such as, points, lines, line strip, triangle list, triangle strip, and others. See FBGeometryPrimitiveType
for the complete primitive list.
MotionBuilder wraps some common OpenGL drawing commands inside the SDK functions to facilitate quick prototyping. It is quite easy to use as illustrated in the following sample.
FBModelVertexData* lModelVertexData = lModel->ModelVertexData;
const int lSubRegionCount = lModelVertexData->GetSubRegionCount();
lModelVertexData->EnableOGLVertexData(); //Bind Vertex Array or Vertex Buffer Object.
for(int lSubRegionIdx = 0; lSubRegionIdx < lSubRegionCount; ++lSubRegionIdx)
{
FBMaterial* lMaterial = lModel->Materials[lSubRegionIdx];
lMaterial->OGLInit();
// Draw all the sub patches inside this sub region.
lModelVertexData->DrawSubRegion(lSubRegionIdx);
}
lModelVertexData->DisableOGLVertexData(); //Unbind Vertex Array or Vertex Buffer Object.
Generally, these vertex buffer arrays are accessible in the CPU main memory. MotionBuilder also takes care of the vertex buffer object when uploading to the GPU device for rendering (if using the CPU deformation mode). In the GPU deformation mode, to access certain model’s deformation result in the CPU main memory, you need to call the FBModelVertexData::VertexArrayMappingRequest()
function beforehand. Also, it is common to combine certain model’s vertex array data into a single VBO for better performance, and thus they only differ in the vertex array offset. For more information, see FBModelVertexData::GetVertexArrayVBOId()
and FBModelVertexData::GetVertexArrayVBOOffset()
.
Displayable Entities
The following determine whether the models are displayed in the viewport:
The model’s Show property is off.
The animatable Visibility property is off.
Any node’s Visibility in the upper level parent/child hierarchy is off, and all the Visibility Inheritance properties in between the hierarchy are on.
Owner group's Show property and owner set’s Visibility value.
You can use the FBModel::IsVisible()
function to get the visibility information at the current frame without handling this visibility determination logic.
All of the displayable entities are not rendered in the viewport as in the following cases:
- Locators are not rendered in the Model Only display mode.
- Models outside of the current camera’s frustum.
The following set of functions and properties in the FBRenderer
class are useful for determining the displayable models and lights in a scene:
FBPropertyInt DisplayableGeometryCount;
FBModel* GetDisplayableGeometry(int pIndex);
const FBModelList& GetDisplayableGeometryInCameraFrustum(FBModelList*, FBCamera*);
bool IsModelInsideCameraFrustum(FBModel* pGeometry, FBCamera* pCamera = NULL);
FBPropertyInt DisplayableLightCount;
FBLight* GetDisplayableLight(int pIndex);
Frame Skip Optimization
Dense geometry rendering and deformation are demanding tasks that affect the performance. A visibility based optimization is implemented in MotionBuilder to resolve this performance issue. If a deformable model’s roughly estimated bound box is not inside any display volume such as, the current camera’s view frustum, the light’s shadow volume or reflection view frustum, and if it does not contribute to the final viewport image for several frames, then the deformation tasks are avoided for a while until the time when the model is required for rendering.
Sometimes even a node's transformation need not be evaluated if the Show and Visibility properties are off, and there are no other dependant nodes (either through parent/child hierarchy or constraint relationship) whose transformation needs to be evaluated.
While this optimization works well in most cases, sometimes you might encounter an unexpected behavior.
The optimization can be toggled on and off at different levels and aspects in the following ways:
- Use the
FBEvaluateManager::FrameSkipOptimization
property to toggle frame skip optimization globally. - Use the
FBModel::ForceAlwaysEvaluate()
function to always evaluate a model or stop skipping. - The shortcut (Ctrl+Shift+P) can toggle the frustum culling globally. You can also use the
Display
EarlyFrustumCulling
preference. - The
FBModel::NoFrustumCullingRequire()
andFBModel::NoFrustumCullingRelease()
functions are used for controlling the frustum culling behavior for each model.
Material
MotionBuilder provides the Phong type material only. You can use this material to set up the Emissive, Ambient, Diffuse, Specularity, and Shiness properties. Other properties (includes Transparency, Reflectivity, Displacement, Bump Map, and Normal Map) are also available if the FBRenderer::AdvancedMaterialMode
property is on.
Most of the material properties are animatable color vectors, and you can also connect texture objects (FBTextrue
type) to each material channel for mapping with the default UV set. For more information, see the FBMaterial
class interface. A single material object can be shared by multiple models, and a single model can be mapped by multiple materials (if the underling geometry has multiple material regions).
The following figure shows the Material Settings pane. You can connect many properties in this pane to the texture objects.
As shown in the above figure, you can drag the material icon from the Asset Browser Templates
Shading Elements, and drop it on a model in the viewport. MotionBuilder automatically creates a new instance of the material and connects it to the model (or replaces any existing material). The sample Python script in
You might want to use custom materials with additional properties flowing through the data pipeline. This can be achieved by subclassing FBMaterial
. For example, see the sample in
Textures and Video
MotionBuilder can load a range of image formats (including BMP, DDS, JPG, PNG, SGI, TAG, TIF, and others). You can also import some common video codecs through QuickTime framework, but make sure that the latest version of the Apple QuickTime is installed. Currently, MotionBuilder does not support video in Linux, but you can use the image sequence instead.
Enhanced DirectDraw Surface (DDS) Support
The DDS compressed texture format support is updated. You can load ATI1, ATI2, BC4, and BC5 texture files from the disk. It is a preferable method because the fast texture uploading and optimal GPU memory consumption provides a high rendering quality. Unlike the other image formats, MotionBuilder does not decompress the DDS texture into the CPU main memory.
Uniform Resource Identifier (URI) Only Texture
You might want to load other image types directly in plug-ins using the standard UIs (such as the File Open dialog) to provide a consistent end user interaction. To achieve this, you can register the external image file extension (suffix) in the codec manager (FBVideoCodecManager
), which allows the extension to appear in the file dialog’s filter section, and ensure that the file path of the external image exists in the FBX file.
/** Register the external video format suffix. Only alphabets and numbers are allowed in the suffix,
* and it cannot be empty or an existing suffix. This allows the suffix to
* appear in the filters of the file dialog when importing video, also allows to create a texture/video
* object with a path containing this suffix using the SDK. However it is the custom SDK plug-in
* developer's responsibility to load the file into memory.
*
* \remarks After registering an external video format, and saving a scene with this kind of video.
* when MotionBuilder starts next time and before loading the scene back,
* \remarks it is necessary to call RegisterExternalVideoFormat to register this kind of video format
* again, otherwise this kind of video will not be loaded.
* \param pFormatSuffix Suffix/File extension of the external video file format
* \return true if register is successful
*/
static bool RegisterExternalVideoFormat( const char* pFormatSuffix );
Layered Texture
Layered texture provides a simple and efficient way for real-time blending between the multiple texture layers. Each layer can have animatable properties, and it can refer to a static image, video sequence, or even live stream input. The following figure shows the Layer Settings pane.
By default, MotionBuilder supports Translucent, Additive, Modulate, and Modulate2 blending modes, but you can subclass the FBLayeredTexture
class and extend its functionality easily. For example, see the sample in
Procedure Texture
You can also use the FBVideoMemory
class to provide arbitrary texture content such as, the static image file, video sequence, or dynamic procedure content. First, you need to provide a valid OpenGL texture buffer object’s ID with its data properly updated, and its dimension information. Next, set this video object as the source of the texture and it joins the rest of the regular MotionBuilder rendering workflow seamlessly. For example, see
Heads Up Display (HUD)
The HUD system is updated for a flexible layout, enhanced display quality through Scaleform technique, easier information retrieving (for example, you can reference any properties and get its current value displayed in the viewport), and for some common built-in element types (for example, Bloop Slate, Record Light, Timeline, and others). Please refer to the user's guide for more information.
You can also extend the default provision by subclassing the FBHUDElement
class. For example, see the sample in
In the following figure, the sample custom HUD element shows a currently selected model in the viewport.
You can also create a custom FBManipulator
to allow interaction with the HUD elements using mouse buttons and move operations in the viewport.