first drivers variant

remade shape keys
separated keyframe channels
This commit is contained in:
devZoGok
2021-10-19 19:06:41 +03:00
parent c91a7f39f6
commit 179aa2789b
20 changed files with 295 additions and 107 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ set(utils util.cpp)
set(math quaternion.cpp vector.cpp matrix.cpp ray.cpp)
set(render particleEmitter.cpp camera.cpp light.cpp material.cpp mesh.cpp model.cpp node.cpp quad.cpp box.cpp root.cpp shader.cpp texture.cpp)
set(model modelReader.cpp assimpModelReader.cpp vbModelReader.cpp)
set(anim animationController.cpp animationChannel.cpp animation.cpp animatable.cpp)
set(anim animationController.cpp animationChannel.cpp animation.cpp keyframeChannel.cpp animatable.cpp driver.cpp)
set(armature skeleton.cpp bone.cpp ikSolver.cpp)
set(library ${render} ${math} ${model} ${utils} ${gui} ${armature} ${assetManager} ${anim})
-4
View File
@@ -8,14 +8,10 @@ namespace vb01{
class Animatable{
public:
enum Type{NODE, BONE};
Animatable();
virtual void animate(float, KeyframeChannel){}
inline Type getType(){return type;}
private:
protected:
Type type;
};
}
+1 -32
View File
@@ -3,39 +3,13 @@
#include <string>
#include <vector>
#include "keyframeChannel.h"
namespace vb01{
class Animatable;
class Animation{
public:
struct KeyframeChannel{
enum Type{
POS_X,
POS_Y,
POS_Z,
ROT_W,
ROT_X,
ROT_Y,
ROT_Z,
SCALE_X,
SCALE_Y,
SCALE_Z,
VALUE
};
struct Keyframe{
enum Interpolation{CONSTANT, LINEAR, BEZIER};
float value;
int frame;
Interpolation interpolation;
};
Type type;
Animatable *animatable = nullptr;
std::vector<Keyframe> keyframes;
};
Animation(std::string);
~Animation();
void update();
@@ -49,11 +23,6 @@ namespace vb01{
std::string name;
std::vector<KeyframeChannel> keyframeChannels;
};
typedef Animation::KeyframeChannel KeyframeChannel;
typedef Animation::KeyframeChannel::Type KeyframeChannelType;
typedef Animation::KeyframeChannel::Keyframe Keyframe;
typedef Animation::KeyframeChannel::Keyframe::Interpolation KeyframeInterpolation;
}
#endif
+6 -32
View File
@@ -14,55 +14,29 @@ namespace vb01{
void AnimationController::update(){
for(AnimationChannel *channel : channels){
channel->update();
transform(channel);
}
}
Keyframe AnimationController::findKeyframe(AnimationChannel *channel, KeyframeChannel keyframeChannel, bool last){
int pastKeyframeId = -1;
for(int i = 0; i < keyframeChannel.keyframes.size(); i++){
Keyframe keyframe = keyframeChannel.keyframes[i];
if(channel->getCurrentFrame() >= keyframe.frame){
pastKeyframeId = i;
}
}
return keyframeChannel.keyframes[pastKeyframeId + (last ? 0 : 1)];
}
void AnimationController::transform(AnimationChannel *channel){
Animation *animation = getAnimation(channel->getAnimationName());
for(Animatable *animatable : channel->getAnimatables()){
vector<KeyframeChannel> keyframeChannels = animation->getKeyframeChannelsByAnimatable(animatable);
for(KeyframeChannel keyframeChannel : keyframeChannels){
Keyframe pastKeyframe = findKeyframe(channel, keyframeChannel, true);
Keyframe nextKeyframe = findKeyframe(channel, keyframeChannel, false);
int currentFrame = channel->getCurrentFrame();
Keyframe pastKeyframe = KeyframeChannel::findKeyframe(currentFrame, keyframeChannel, true);
Keyframe nextKeyframe = KeyframeChannel::findKeyframe(currentFrame, keyframeChannel, false);
int pastFrame = pastKeyframe.frame;
int nextFrame = nextKeyframe.frame;
float ratio = (float)(max(0, channel->getCurrentFrame() - pastFrame)) / (nextFrame - pastFrame);
float ratio = (float)(max(0, currentFrame - pastFrame)) / (nextFrame - pastFrame);
Keyframe::Interpolation interp = pastKeyframe.interpolation;
float value = interpolate(pastKeyframe.value, nextKeyframe.value, interp, ratio);
float value = KeyframeChannel::interpolate(pastKeyframe.value, nextKeyframe.value, interp, ratio);
animatable->animate(value, keyframeChannel);
}
}
}
float AnimationController::interpolate(float pastValue, float nextValue, Keyframe::Interpolation mode, float ratio){
float currentValue;
switch(mode){
case Keyframe::CONSTANT:
currentValue = pastValue;
break;
case Keyframe::LINEAR:
currentValue = pastValue + (nextValue - pastValue) * ratio;
break;
case Keyframe::BEZIER:
currentValue = pastValue + (nextValue - pastValue) * ratio;
break;
}
return currentValue;
}
Animation* AnimationController::getAnimation(string name){
Animation *anim = nullptr;
for(Animation *a : animations)
-2
View File
@@ -26,8 +26,6 @@ namespace vb01{
std::vector<AnimationChannel*> channels;
void transform(AnimationChannel*);
Keyframe findKeyframe(AnimationChannel*, KeyframeChannel, bool);
float interpolate(float, float, Keyframe::Interpolation, float);
protected:
void onAnimationEnd(std::string){}
void onAnimationStart(std::string){}
+37 -1
View File
@@ -7,7 +7,6 @@ namespace vb01{
Bone::Bone(string name, float length, Vector3 pos, Quaternion rot, Vector3 scale) : Node(pos, rot, scale, name){
this->name = name;
this->length = length;
Animatable::type = Animatable::BONE;
}
void Bone::lookAt(Vector3 newDir, Vector3 newUp){
@@ -118,4 +117,41 @@ namespace vb01{
setPoseRot(newRot);
setPoseScale(newScale);
}
float Bone::getDriverValue(Driver::VariableType type){
float driverValue;
switch(type){
case Driver::POS_X:
driverValue = posePos.x;
break;
case Driver::POS_Y:
driverValue = posePos.y;
break;
case Driver::POS_Z:
driverValue = posePos.z;
break;
case Driver::ROT_W:
driverValue = poseRot.w;
break;
case Driver::ROT_X:
driverValue = poseRot.x;
break;
case Driver::ROT_Y:
driverValue = poseRot.y;
break;
case Driver::ROT_Z:
driverValue = poseRot.z;
break;
case Driver::SCALE_X:
driverValue = poseScale.x;
break;
case Driver::SCALE_Y:
driverValue = poseScale.y;
break;
case Driver::SCALE_Z:
driverValue = poseScale.z;
break;
}
return driverValue;
}
}
+1
View File
@@ -35,6 +35,7 @@ namespace vb01{
private:
void updateBoneInfo();
void animate(float, KeyframeChannel);
virtual float getDriverValue(Driver::VariableType);
float length;
Bone *ikTarget = nullptr;
+25
View File
@@ -0,0 +1,25 @@
#include "driver.h"
#include "animatable.h"
#include <algorithm>
using namespace std;
namespace vb01{
Driver::Driver(){}
void Driver::drive(float driverValue){
Keyframe pastKeyframe = KeyframeChannel::findKeyframe(driverValue, keyframeChannel, true);
Keyframe nextKeyframe = KeyframeChannel::findKeyframe(driverValue, keyframeChannel, false);
float pastFrame = pastKeyframe.frame;
float nextFrame = nextKeyframe.frame;
float ratio = (float)(driverValue - pastFrame) / (nextFrame - pastFrame);
if(ratio < 0)
ratio = 0;
Keyframe::Interpolation interp = pastKeyframe.interpolation;
float value = KeyframeChannel::interpolate(pastKeyframe.value, nextKeyframe.value, interp, ratio);
target->animate(value, keyframeChannel);
}
}
+34
View File
@@ -0,0 +1,34 @@
#ifndef DRIVER_H
#define DRIVER
#include "keyframeChannel.h"
namespace vb01{
class Animatable;
class Driver{
public:
enum VariableType{
POS_X,
POS_Y,
POS_Z,
ROT_W,
ROT_X,
ROT_Y,
ROT_Z,
SCALE_X,
SCALE_Y,
SCALE_Z
};
Driver();
inline VariableType getType(){return type;}
void drive(float);
private:
Animatable *target;
VariableType type;
KeyframeChannel keyframeChannel;
};
}
#endif
+33
View File
@@ -0,0 +1,33 @@
#include "keyframeChannel.h"
namespace vb01{
float KeyframeChannel::interpolate(float pastValue, float nextValue, Keyframe::Interpolation mode, float ratio){
float currentValue;
switch(mode){
case Keyframe::CONSTANT:
currentValue = pastValue;
break;
case Keyframe::LINEAR:
currentValue = pastValue + (nextValue - pastValue) * ratio;
break;
case Keyframe::BEZIER:
currentValue = pastValue + (nextValue - pastValue) * ratio;
break;
}
return currentValue;
}
Keyframe KeyframeChannel::findKeyframe(float time, KeyframeChannel keyframeChannel, bool last){
int pastKeyframeId = -1;
for(int i = 0; i < keyframeChannel.keyframes.size(); i++){
Keyframe keyframe = keyframeChannel.keyframes[i];
if(time >= keyframe.frame){
pastKeyframeId = i;
}
}
return keyframeChannel.keyframes[pastKeyframeId + (last ? 0 : 1)];
}
void KeyframeChannel::transform(){
}
}
+46
View File
@@ -0,0 +1,46 @@
#ifndef KEYFRAME_CHANNEL_H
#define KEYFRAME_CHANNEL_H
#include <vector>
namespace vb01{
class Animatable;
struct KeyframeChannel{
enum Type{
POS_X,
POS_Y,
POS_Z,
ROT_W,
ROT_X,
ROT_Y,
ROT_Z,
SCALE_X,
SCALE_Y,
SCALE_Z,
SHAPE_KEY_MIN,
SHAPE_KEY_VALUE,
SHAPE_KEY_MAX
};
struct Keyframe{
enum Interpolation{CONSTANT, LINEAR, BEZIER};
float value, frame;
Interpolation interpolation;
};
Type type;
Animatable *animatable = nullptr;
std::vector<Keyframe> keyframes;
static float interpolate(float, float, Keyframe::Interpolation, float);
static Keyframe findKeyframe(float, KeyframeChannel, bool);
static void transform();
};
typedef KeyframeChannel::Type KeyframeChannelType;
typedef KeyframeChannel::Keyframe Keyframe;
typedef KeyframeChannel::Keyframe::Interpolation KeyframeInterpolation;
}
#endif
+33 -17
View File
@@ -1,22 +1,37 @@
#include"root.h"
#include"node.h"
#include"box.h"
#include"texture.h"
#include"skeleton.h"
#include<glad.h>
#include<glfw3.h>
#include<glm.hpp>
#include<ext.hpp>
#include<iostream>
#include<cstdlib>
#include "root.h"
#include "node.h"
#include "box.h"
#include "texture.h"
#include "skeleton.h"
#include "animation.h"
#include <glad.h>
#include <glfw3.h>
#include <glm.hpp>
#include <ext.hpp>
#include <iostream>
#include <cstdlib>
using namespace std;
using namespace glm;
namespace vb01{
void Mesh::ShapeKey::animate(float value, KeyframeChannel keyframeChannel){
switch(keyframeChannel.type){
case KeyframeChannel::SHAPE_KEY_MIN:
this->minValue = value;
break;
case KeyframeChannel::SHAPE_KEY_VALUE:
this->value = value;
break;
case KeyframeChannel::SHAPE_KEY_MAX:
this->maxValue = value;
break;
}
}
Mesh::Mesh(){}
Mesh::Mesh(Vertex *vertices, unsigned int *indices, int numTris, string *vertexGroups, int numVertexGroups, string *shapeKeys, int numShapeKeys, string name){
Mesh::Mesh(Vertex *vertices, unsigned int *indices, int numTris, string *vertexGroups, int numVertexGroups, ShapeKey *shapeKeys, int numShapeKeys, string name) : Animatable(){
this->vertices = vertices;
this->indices = indices;
this->numTris = numTris;
@@ -25,10 +40,6 @@ namespace vb01{
this->shapeKeys = shapeKeys;
this->numShapeKeys = numShapeKeys;
this->name = name;
shapeKeyFactors = new float[numShapeKeys];
for(int i = 0; i < numShapeKeys; i++)
shapeKeyFactors[i] = 0;
}
Mesh::~Mesh(){
@@ -164,7 +175,12 @@ namespace vb01{
void Mesh::updateShapeKeys(Shader *shader){
shader->editShader(Shader::VERTEX_SHADER, 5, "const int numShapeKeys=" + to_string(numShapeKeys) + ";");
for(int i = 0; i < numShapeKeys; i++){
shader->setFloat(shapeKeyFactors[i], "shapeKeyFactors[" + to_string(i) + "]");
if(shapeKeys[i].value < shapeKeys[i].minValue)
shapeKeys[i].value = shapeKeys[i].minValue;
else if(shapeKeys[i].value > shapeKeys[i].maxValue)
shapeKeys[i].value = shapeKeys[i].maxValue;
shader->setFloat(shapeKeys[i].value, "shapeKeyFactors[" + to_string(i) + "]");
}
}
+15 -10
View File
@@ -1,12 +1,12 @@
#ifndef MESH_H
#define MESH_H
#include"vector.h"
#include"util.h"
#include<vector>
#include<string>
#include"material.h"
#include "vector.h"
#include "util.h"
#include "material.h"
#include "animatable.h"
#include <vector>
#include <string>
namespace vb01{
class Node;
@@ -14,8 +14,13 @@ namespace vb01{
class Texture;
class Skeleton;
class Mesh{
class Mesh : public Animatable{
public:
struct ShapeKey{
float minValue, value, maxValue;
void animate(float, KeyframeChannel);
};
struct Vertex{
Vector3 pos, norm, tan, biTan;
Vector2 uv;
@@ -24,7 +29,7 @@ namespace vb01{
Vector3 shapeKeyOffsets[100];
};
Mesh(Vertex*, u32*, int, std::string *vg = nullptr, int = 0, std::string *sk = nullptr, int = 0, std::string = "");
Mesh(Vertex*, u32*, int, std::string *vg = nullptr, int = 0, ShapeKey *sk = nullptr, int = 0, std::string = "");
~Mesh();
void construct();
virtual void update();
@@ -66,9 +71,9 @@ namespace vb01{
bool staticVerts = true, castShadow = false, reflect = false, wireframe = false;
Vertex *vertices;
std::string *vertexGroups = nullptr, *shapeKeys = nullptr;
std::string *vertexGroups = nullptr;
ShapeKey *shapeKeys = nullptr;
u32 *indices, VAO, VBO, EBO;
float *shapeKeyFactors = nullptr;
int numTris, numVertexGroups = 0, numShapeKeys = 0;
};
}
+39 -1
View File
@@ -21,7 +21,6 @@ namespace vb01{
this->orientation = orientation;
this->name = name;
this->controller = controller;
Animatable::type = Animatable::NODE;
globalAxis[0] = Vector3::VEC_I;
globalAxis[1] = Vector3::VEC_J;
@@ -58,6 +57,45 @@ namespace vb01{
if(controller)
controller->update();
}
for(Driver &driver : drivers)
driver.drive(getDriverValue(driver.getType()));
}
float Node::getDriverValue(Driver::VariableType type){
float driverValue;
switch(type){
case Driver::POS_X:
driverValue = pos.x;
break;
case Driver::POS_Y:
driverValue = pos.y;
break;
case Driver::POS_Z:
driverValue = pos.z;
break;
case Driver::ROT_W:
driverValue = orientation.w;
break;
case Driver::ROT_X:
driverValue = orientation.x;
break;
case Driver::ROT_Y:
driverValue = orientation.y;
break;
case Driver::ROT_Z:
driverValue = orientation.z;
break;
case Driver::SCALE_X:
driverValue = scale.x;
break;
case Driver::SCALE_Y:
driverValue = scale.y;
break;
case Driver::SCALE_Z:
driverValue = scale.z;
break;
}
return driverValue;
}
void Node::attachChild(Node *child){
+3
View File
@@ -5,6 +5,7 @@
#include "vector.h"
#include "root.h"
#include "animatable.h"
#include "driver.h"
#include <vector>
#include <string>
@@ -73,8 +74,10 @@ namespace vb01{
Quaternion adjustRot(std::vector<Node*>, Quaternion, bool);
AnimationController *controller = nullptr;
std::vector<Driver> drivers;
protected:
virtual void animate(float, KeyframeChannel);
virtual float getDriverValue(Driver::VariableType);
bool visible = true;
Vector3 pos, scale, globalAxis[3];
+1 -1
View File
@@ -14,7 +14,7 @@ namespace vb01{
inFile.close();
}
void getLineData(string &line, string data[], int numData, int offset){
void getLineData(string line, string data[], int numData, int offset){
int offsetComma = 0, c1 = 0;
for(int i = 0; i < line.length() && offsetComma < offset; i++)
if(line.c_str()[i] == ' '){
+1 -1
View File
@@ -20,7 +20,7 @@ namespace vb01{
static const float PI = 4 * atan(1);
void readFile(std::string, std::vector<std::string>&, int = 0, int = -1);
void getLineData(std::string&, std::string[], int, int = 0);
void getLineData(std::string, std::string[], int, int = 0);
int getCharId(std::string, char, bool = false);
inline s64 getTime(){return s64(std::chrono::system_clock::now().time_since_epoch() / std::chrono::milliseconds(1));}
+12 -4
View File
@@ -344,7 +344,7 @@ namespace vb01{
}
}
void VbModelReader::readShapeKeys(Mesh::Vertex *vertices, vector<u32> &vertIds, vector<string> &meshData, string *shapeKeys, int numShapes, int numVertPos){
void VbModelReader::readShapeKeys(Mesh::Vertex *vertices, vector<u32> &vertIds, vector<string> &meshData, Mesh::ShapeKey *shapeKeys, int numShapes, int numVertPos){
/*
for(int i = 0; i < vertIds.size(); i++)
vertices[i].shapeKeyOffsets = new Vector3[numShapes];
@@ -352,9 +352,17 @@ namespace vb01{
int shapeKeyStartLine = 0;
for(int i = 0; i < numShapes; i++){
shapeKeys[i] = meshData[shapeKeyStartLine];
Vector3 *shapeKeyVertPos = new Vector3[numVertPos];
string line = meshData[shapeKeyStartLine];
int colonId = line.find_first_of(':');
Mesh::ShapeKey shapeKey;
string data[2];
getLineData(line.substr(colonId + 1), data, 2);
shapeKey.minValue = atof(data[0].c_str());
shapeKey.value = shapeKey.minValue;
shapeKey.maxValue = atof(data[1].c_str());
shapeKeys[i] = shapeKey;
Vector3 *shapeKeyVertPos = new Vector3[numVertPos];
for(int j = 0; j < numVertPos; j++){
string line = meshData[shapeKeyStartLine + 1 + j];
string dataLine[3];
@@ -407,7 +415,7 @@ namespace vb01{
Mesh::Vertex *vertices = new Mesh::Vertex[numFaces * numVertsPerFace];
u32 *indices = new u32[numFaces * numVertsPerFace];
string *groups = new string[numBones];
string *shapeKeys = new string[numShapes];
Mesh::ShapeKey *shapeKeys = new Mesh::ShapeKey[numShapes];
vector<string> meshSubData = vector<string>(meshData.begin() + vertexStartLine, meshData.begin() + vertexStartLine + numVertices);
readVertices(vertPos, vertNorm, vertWeights, meshSubData, numBones);
+1 -1
View File
@@ -30,7 +30,7 @@ namespace vb01{
void readVertices(std::vector<Vector3>&, std::vector<Vector3>&, std::vector<float>&, std::vector<std::string>&, int);
void readFaces(std::vector<Vector3>&, std::vector<Vector3>&, std::vector<u32>&, std::vector<float>&, std::vector<std::string>&, int, Mesh::Vertex*, u32*);
void readVertexGroups(std::string*, std::vector<std::string>&, int);
void readShapeKeys(Mesh::Vertex*, std::vector<u32>&, std::vector<std::string>&, std::string*, int, int);
void readShapeKeys(Mesh::Vertex*, std::vector<u32>&, std::vector<std::string>&, Mesh::ShapeKey*, int, int);
void buildMesh(std::vector<std::string>&);
Mesh* readMeshes(std::vector<std::string>&);
void readLights(std::vector<std::string>&);
+6
View File
@@ -143,6 +143,12 @@ namespace vb01{
meshData.push_back(to_string(i) + " " + uvString + tanString + biTanString);
}
meshData.push_back("shapeKeys: 0");
meshData.push_back("Key 1: 0 1");
for(int i = 0; i < vertPos.size(); i++){
Vector3 pos = vertPos[i];
string posString = to_string(pos.x) + " " + to_string(pos.y) + " " + to_string(pos.z) + " ";
meshData.push_back(posString);
}
meshData.push_back("animations: 0");
}