-
-
Notifications
You must be signed in to change notification settings - Fork 29
Adding .FBX objects with Blend Shapes
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.
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.
#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();
}
};
Any recommendations on additional information to add can be requested in the discussions tab. If you have additional questions, you can @ me in my Discord server or on direct message me on Twitter.