Skip to content

Adding .FBX objects with Blend Shapes

Coela Can't! edited this page Aug 20, 2021 · 2 revisions

Filmbox .FBX Files

Much like .OBJ files, .FBX files store data for linking vertices to form triangles, UV Maps, as well as blend shapes that can be used to morph the 3D object to a different shape.

Creating a ProtoTracer Object3D with Morph Controllers

To create a ProtoTracer Object3D from a Binary .FBX file, open the ProtoTracerFBXConverter project and open the Converter.py file. Modify the top few lines to fit your input binary file name, the converted ASCII file name, the output C++ file name, and the class name:

origFileName = "Example Files\KaiborgFaceMorphBinary.fbx"
newFileName = "Example Files\KaiborgFaceMorphAscii.fbx"
outputCPPName = "Output\KaiborgV1.h"
name = "KaiborgV1"

Run the python file to create the C++ output header. This file can now be included and directly used within an Animation object.

Using an Object3D with Morph Controllers

#pragma once

// Include necessary files
#include "Animation.h"
#include "KeyFrameTrack.h"
#include "..\Morph\KaiborgV1.h"
#include "..\Render\Scene.h"
#include "..\Materials\GradientMaterial.h"
#include "..\Materials\SimplexNoise.h"

// Create animation class as child of Animation object
class KaiborgV1Animation : public Animation{
private:
    // Include morph object
    KaiborgV1 kbFace;

    // Create KeyFrameTracks for animating parameters
    KeyFrameTrack kbPOGTrack = KeyFrameTrack(10, 0.0f, 1.0f, 10, KeyFrameTrack::Step);
    KeyFrameTrack kbAngryEyesTrack = KeyFrameTrack(10, 0.0f, 1.0f, 10, KeyFrameTrack::Linear);
    KeyFrameTrack kbMouthFrownTrack = KeyFrameTrack(10, 0.0f, 1.0f, 10, KeyFrameTrack::Cosine);

    // Create material preset; this creates a Simplex noise shader with a mapped gradient
    RGBColor spectrum[4] = {RGBColor(0, 0, 0), RGBColor(255, 0, 0), RGBColor(0, 255, 0), RGBColor(0, 0, 255)};
    SimpleMaterial sMat = SimpleMaterial(RGBColor(0, 0, 0));
    GradientMaterial gMat = GradientMaterial(6, spectrum, 150.0f, true);
    GradientMaterial gNoiseMat = GradientMaterial(4, spectrum, 2.0f, false);
    SimplexNoise sNoise = SimplexNoise(1, &gNoiseMat);

    // Pass the floating point reference to be modified into the KeyFrame objects
    void LinkParameters(){
        kbPOGTrack.AddParameter(kbFace.GetMorphWeightReference(KaiborgV1::POG));
        kbAngryEyesTrack.AddParameter(kbFace.GetMorphWeightReference(KaiborgV1::AngryEyes));
        kbMouthFrownTrack.AddParameter(kbFace.GetMorphWeightReference(KaiborgV1::MouthFrown));
    }

    // Add keyframes to track
    void AddPOGKeyFrames(){
        kbPOGTrack.AddKeyFrame(0.0f, 0.0f);
        kbPOGTrack.AddKeyFrame(1.0f, 0.1f);
        kbPOGTrack.AddKeyFrame(2.0f, 0.0f);
    }

    // Add keyframes to track
    void AddAngryEyeKeyFrames(){
        kbAngryEyesTrack.AddKeyFrame(0.0f, 0.0f);
        kbAngryEyesTrack.AddKeyFrame(0.5f, 0.25f);
        kbAngryEyesTrack.AddKeyFrame(1.0f, 0.0f);
        kbAngryEyesTrack.AddKeyFrame(1.5f, 0.25f);
        kbAngryEyesTrack.AddKeyFrame(2.0f, 0.0f);
    }

    // Add keyframes to track
    void AddMouthFrownKeyFrames(){
        kbMouthFrownTrack.AddKeyFrame(0.0f, 1.0f);
        kbMouthFrownTrack.AddKeyFrame(0.2f, 0.0f);
        kbMouthFrownTrack.AddKeyFrame(0.4f, 1.0f);
        kbMouthFrownTrack.AddKeyFrame(0.6f, 0.0f);
        kbMouthFrownTrack.AddKeyFrame(0.8f, 1.0f);
        kbMouthFrownTrack.AddKeyFrame(1.0f, 0.0f);
        kbMouthFrownTrack.AddKeyFrame(2.0f, 0.0f);
    }

public:
    // Create animation constructor and call parent constructor with max objects in the scene
    KaiborgV1Animation() : Animation(1){
        // Add the base Object3D from the morph object to the Animation Scene
        scene->AddObject(kbFace.GetObject());
        
        // Link parameters and add key frames to key frame tracks
        LinkParameters();
        AddPOGKeyFrames();
        AddAngryEyeKeyFrames();
        AddMouthFrownKeyFrames();
        
        // Link material to Object3D if not using a UV Map material
        kbFace.GetObject()->SetMaterial(&sNoise);
    }

    // Override FadeIn function
    void FadeIn(float stepRatio) override {}

    // Override FadeIn function
    void FadeOut(float stepRatio) override {}

    // Allow external use and modification of the Object3D reference
    Object3D* GetObject(){
        return kbFace.GetObject();
    }

    // Override update function, pass in the current ratio of completion for the animation 0.0f -> 1.0f linear ramp
    void Update(float ratio) override {
        // Manually define parameter control functions or implement FunctionGenerator instances above
        float x = sinf(ratio * 3.14159f / 180.0f * 360.0f) * 50.0f;
        float y = cosf(ratio * 3.14159f / 180.0f * 360.0f) * 50.0f;
        float linSweep = ratio > 0.5f ? 1.0f - ratio : ratio;
        float sShift = linSweep * 0.0075f + 0.01f;

        //Change material parameters
        sMat.HueShift(ratio * 360 * 4);
        gMat.SetGradientPeriod(150.0f + x * 150.0f);
        gMat.SetPositionOffset(Vector2D(x * 2.0f, 100.0f + y * 2.0f));
        gNoiseMat.HueShift(ratio * 360 * 2);
        sNoise.SetScale(Vector3D(sShift, sShift, sShift));
        sNoise.SetZPosition(x * 6.0f);

        //Example of Face with slight movement, scaling, and rotation
        kbPOGTrack.Update();
        kbAngryEyesTrack.Update();
        kbMouthFrownTrack.Update();

        // Update the morphs on the morph object
        kbFace.Update();

        //Objects visibility can be enabled and disabled at any point before rasterizing to change its visibility
        kbFace.GetObject()->Enable();//

        //Objects can be moved to a coordinate or translated by a vector
        kbFace.GetObject()->GetTransform()->SetPosition(Vector3D(35.0f, 20.0f, 600.0f));

        //Objects can be rotated with by any rotation object (quaternion is preferred) and about any coordinate or center
        kbFace.GetObject()->GetTransform()->SetRotation(Vector3D(sinf(ratio * 3.14159f / 180.0f * 1440.0f) * 1.0f, sinf(ratio * 3.14159f / 180.0f * 720.0f) * 1.0f, 1));

        //Objects can be scaled by origin, center, and at a point
        float s = 1.0f + sin(ratio * 3.14159f / 180.0f * 2160.0f) * 0.03f;
        kbFace.GetObject()->GetTransform()->SetScale(Vector3D(s, s, s));

        // Update the transform of the object to apply the transformation
        kbFace.GetObject()->UpdateTransform();
    }
};