mirror of
https://github.com/devZoGok/vb01.git
synced 2026-08-26 19:43:30 +00:00
drivers reading
This commit is contained in:
@@ -13,31 +13,6 @@ namespace vb01{
|
||||
void Animation::update(){
|
||||
}
|
||||
|
||||
KeyframeChannelType Animation::getKeyframeChannelType(string typeString){
|
||||
KeyframeChannelType type;
|
||||
if(typeString == "pos_x")
|
||||
type = KeyframeChannelType::POS_X;
|
||||
else if(typeString == "pos_y")
|
||||
type = KeyframeChannelType::POS_Y;
|
||||
else if(typeString == "pos_z")
|
||||
type = KeyframeChannelType::POS_Z;
|
||||
else if(typeString == "rot_w")
|
||||
type = KeyframeChannelType::ROT_W;
|
||||
else if(typeString == "rot_x")
|
||||
type = KeyframeChannelType::ROT_X;
|
||||
else if(typeString == "rot_y")
|
||||
type = KeyframeChannelType::ROT_Y;
|
||||
else if(typeString == "rot_z")
|
||||
type = KeyframeChannelType::ROT_Z;
|
||||
else if(typeString == "scale_x")
|
||||
type = KeyframeChannelType::SCALE_X;
|
||||
else if(typeString == "scale_y")
|
||||
type = KeyframeChannelType::SCALE_Y;
|
||||
else if(typeString == "scale_z")
|
||||
type = KeyframeChannelType::SCALE_Z;
|
||||
return type;
|
||||
}
|
||||
|
||||
KeyframeChannel* Animation::getKeyframeChannel(Animatable *animatable, KeyframeChannelType type){
|
||||
KeyframeChannel *k = nullptr;
|
||||
|
||||
|
||||
+1
-1
@@ -13,9 +13,9 @@ namespace vb01{
|
||||
Animation(std::string);
|
||||
~Animation();
|
||||
void update();
|
||||
static KeyframeChannel::Type getKeyframeChannelType(std::string);
|
||||
KeyframeChannel* getKeyframeChannel(Animatable*, KeyframeChannel::Type);
|
||||
std::vector<KeyframeChannel> getKeyframeChannelsByAnimatable(Animatable*);
|
||||
inline void addKeyframeChannels(std::vector<KeyframeChannel> keyframeChannels){this->keyframeChannels.assign(keyframeChannels.begin(), keyframeChannels.end());}
|
||||
inline void addKeyframeChannel(KeyframeChannel channel){keyframeChannels.push_back(channel);}
|
||||
inline std::string getName(){return name;}
|
||||
inline const std::vector<KeyframeChannel>& getKeyframeChannels(){return keyframeChannels;}
|
||||
|
||||
+30
-2
@@ -6,7 +6,10 @@
|
||||
using namespace std;
|
||||
|
||||
namespace vb01{
|
||||
Driver::Driver(){}
|
||||
Driver::Driver(KeyframeChannel keyframeChannel, VariableType type){
|
||||
this->keyframeChannel = keyframeChannel;
|
||||
this->type = type;
|
||||
}
|
||||
|
||||
void Driver::drive(float driverValue){
|
||||
Keyframe pastKeyframe = KeyframeChannel::findKeyframe(driverValue, keyframeChannel, true);
|
||||
@@ -20,6 +23,31 @@ namespace vb01{
|
||||
|
||||
Keyframe::Interpolation interp = pastKeyframe.interpolation;
|
||||
float value = KeyframeChannel::interpolate(pastKeyframe.value, nextKeyframe.value, interp, ratio);
|
||||
target->animate(value, keyframeChannel);
|
||||
keyframeChannel.animatable->animate(value, keyframeChannel);
|
||||
}
|
||||
|
||||
Driver::VariableType Driver::getDriverVariableType(string typeString){
|
||||
VariableType type;
|
||||
if(typeString == "LOC_X")
|
||||
type = Driver::POS_X;
|
||||
else if(typeString == "LOC_Y")
|
||||
type = Driver::POS_Y;
|
||||
else if(typeString == "LOC_Z")
|
||||
type = Driver::POS_Z;
|
||||
else if(typeString == "ROT_W")
|
||||
type = Driver::ROT_W;
|
||||
else if(typeString == "ROT_X")
|
||||
type = Driver::ROT_X;
|
||||
else if(typeString == "ROT_Y")
|
||||
type = Driver::ROT_Y;
|
||||
else if(typeString == "ROT_Z")
|
||||
type = Driver::ROT_Z;
|
||||
else if(typeString == "SCALE_X")
|
||||
type = Driver::SCALE_X;
|
||||
else if(typeString == "SCALE_Y")
|
||||
type = Driver::SCALE_Y;
|
||||
else if(typeString == "SCALE_Z")
|
||||
type = Driver::SCALE_Z;
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define DRIVER
|
||||
|
||||
#include "keyframeChannel.h"
|
||||
#include <string>
|
||||
|
||||
namespace vb01{
|
||||
class Animatable;
|
||||
@@ -21,11 +22,12 @@ namespace vb01{
|
||||
SCALE_Z
|
||||
};
|
||||
|
||||
Driver();
|
||||
inline VariableType getType(){return type;}
|
||||
Driver(KeyframeChannel, VariableType);
|
||||
void drive(float);
|
||||
static VariableType getDriverVariableType(std::string);
|
||||
inline VariableType getType(){return type;}
|
||||
inline KeyframeChannel& getKeyframeChannel(){return keyframeChannel;}
|
||||
private:
|
||||
Animatable *target;
|
||||
VariableType type;
|
||||
KeyframeChannel keyframeChannel;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "keyframeChannel.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace vb01{
|
||||
float KeyframeChannel::interpolate(float pastValue, float nextValue, Keyframe::Interpolation mode, float ratio){
|
||||
float currentValue;
|
||||
@@ -17,6 +19,37 @@ namespace vb01{
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
KeyframeChannelType KeyframeChannel::getKeyframeChannelType(string typeString){
|
||||
KeyframeChannelType type;
|
||||
if(typeString == "pos_x")
|
||||
type = KeyframeChannelType::POS_X;
|
||||
else if(typeString == "pos_y")
|
||||
type = KeyframeChannelType::POS_Y;
|
||||
else if(typeString == "pos_z")
|
||||
type = KeyframeChannelType::POS_Z;
|
||||
else if(typeString == "rot_w")
|
||||
type = KeyframeChannelType::ROT_W;
|
||||
else if(typeString == "rot_x")
|
||||
type = KeyframeChannelType::ROT_X;
|
||||
else if(typeString == "rot_y")
|
||||
type = KeyframeChannelType::ROT_Y;
|
||||
else if(typeString == "rot_z")
|
||||
type = KeyframeChannelType::ROT_Z;
|
||||
else if(typeString == "scale_x")
|
||||
type = KeyframeChannelType::SCALE_X;
|
||||
else if(typeString == "scale_y")
|
||||
type = KeyframeChannelType::SCALE_Y;
|
||||
else if(typeString == "scale_z")
|
||||
type = KeyframeChannelType::SCALE_Z;
|
||||
else if(typeString == "shape_key_min")
|
||||
type = KeyframeChannelType::SHAPE_KEY_MIN;
|
||||
else if(typeString == "shape_key_value")
|
||||
type = KeyframeChannelType::SHAPE_KEY_VALUE;
|
||||
else if(typeString == "shape_key_max")
|
||||
type = KeyframeChannelType::SHAPE_KEY_MAX;
|
||||
return type;
|
||||
}
|
||||
|
||||
Keyframe KeyframeChannel::findKeyframe(float time, KeyframeChannel keyframeChannel, bool last){
|
||||
int pastKeyframeId = -1;
|
||||
for(int i = 0; i < keyframeChannel.keyframes.size(); i++){
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define KEYFRAME_CHANNEL_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace vb01{
|
||||
class Animatable;
|
||||
@@ -33,6 +34,7 @@ namespace vb01{
|
||||
Animatable *animatable = nullptr;
|
||||
std::vector<Keyframe> keyframes;
|
||||
|
||||
static KeyframeChannel::Type getKeyframeChannelType(std::string);
|
||||
static float interpolate(float, float, Keyframe::Interpolation, float);
|
||||
static Keyframe findKeyframe(float, KeyframeChannel, bool);
|
||||
static void transform();
|
||||
|
||||
@@ -16,7 +16,8 @@ namespace vb01{
|
||||
|
||||
class Mesh : public Animatable{
|
||||
public:
|
||||
struct ShapeKey{
|
||||
struct ShapeKey : public Animatable{
|
||||
std::string name;
|
||||
float minValue, value, maxValue;
|
||||
|
||||
void animate(float, KeyframeChannel);
|
||||
@@ -51,6 +52,8 @@ namespace vb01{
|
||||
inline std::string* getVertexGroups(){return vertexGroups;}
|
||||
inline int getNumVertexGroups(){return numVertexGroups;}
|
||||
inline u32* getIndices(){return indices;}
|
||||
inline ShapeKey& getShapeKey(int i){return shapeKeys[i];}
|
||||
inline int getNumShapeKeys(){return numShapeKeys;}
|
||||
private:
|
||||
void initMesh();
|
||||
void initFramebuffer();
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
#include"model.h"
|
||||
#include"mesh.h"
|
||||
#include"material.h"
|
||||
#include"vector.h"
|
||||
#include"util.h"
|
||||
#include"bone.h"
|
||||
#include"root.h"
|
||||
#include"skeleton.h"
|
||||
#include"animation.h"
|
||||
#include"vbModelReader.h"
|
||||
#include"assimpModelReader.h"
|
||||
#include "model.h"
|
||||
#include "mesh.h"
|
||||
#include "material.h"
|
||||
#include "vector.h"
|
||||
#include "util.h"
|
||||
#include "bone.h"
|
||||
#include "root.h"
|
||||
#include "skeleton.h"
|
||||
#include "animation.h"
|
||||
#include "vbModelReader.h"
|
||||
#include "assimpModelReader.h"
|
||||
|
||||
#include<vector>
|
||||
#include<Importer.hpp>
|
||||
#include<scene.h>
|
||||
#include<postprocess.h>
|
||||
#include<fstream>
|
||||
#include <vector>
|
||||
#include <Importer.hpp>
|
||||
#include <scene.h>
|
||||
#include <postprocess.h>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace Assimp;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef MODEL_H
|
||||
#define MODEL_H
|
||||
|
||||
#include<vector>
|
||||
#include<string>
|
||||
#include"node.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "node.h"
|
||||
|
||||
class aiScene;
|
||||
class aiNode;
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
#ifndef MODEL_READER
|
||||
#define MODEL_READER
|
||||
|
||||
#include<string>
|
||||
#include"model.h"
|
||||
#include <string>
|
||||
#include "model.h"
|
||||
|
||||
namespace vb01{
|
||||
class ModelReader{
|
||||
|
||||
@@ -57,8 +57,8 @@ namespace vb01{
|
||||
if(controller)
|
||||
controller->update();
|
||||
}
|
||||
for(Driver &driver : drivers)
|
||||
driver.drive(getDriverValue(driver.getType()));
|
||||
for(Driver *driver : drivers)
|
||||
driver->drive(getDriverValue(driver->getType()));
|
||||
}
|
||||
|
||||
float Node::getDriverValue(Driver::VariableType type){
|
||||
|
||||
@@ -67,6 +67,7 @@ namespace vb01{
|
||||
inline bool isVisible(){return visible;}
|
||||
inline std::string getName(){return name;}
|
||||
inline void setVisible(bool v){this->visible = v;}
|
||||
inline void addDriver(Driver *d){drivers.push_back(d);}
|
||||
private:
|
||||
void adjustUp(Vector3);
|
||||
void adjustDir(Vector3);
|
||||
@@ -74,7 +75,7 @@ namespace vb01{
|
||||
|
||||
Quaternion adjustRot(std::vector<Node*>, Quaternion, bool);
|
||||
AnimationController *controller = nullptr;
|
||||
std::vector<Driver> drivers;
|
||||
std::vector<Driver*> drivers;
|
||||
protected:
|
||||
virtual void animate(float, KeyframeChannel);
|
||||
virtual float getDriverValue(Driver::VariableType);
|
||||
|
||||
@@ -16,6 +16,7 @@ def exportData(ob):
|
||||
if(ob.animation_data is not None and len(ob.animation_data.nla_tracks) > 0):
|
||||
numAnims = len(ob.animation_data.nla_tracks[0].strips)
|
||||
|
||||
channels = []
|
||||
if(ob.type == 'ARMATURE'):
|
||||
file.write('bones: ' + str(len(ob.data.bones)) + ' ' + str(numAnims) + ' \n')
|
||||
|
||||
@@ -43,8 +44,6 @@ def exportData(ob):
|
||||
chainLength = ikConstraint.chain_count
|
||||
|
||||
file.write(bone.name + ': ' + ('None' if bone.parent is None else bone.parent.name) + " " + str(bone.length) + " " + str(head.x) + " " + str(head.y) + " " + str(head.z) + " " + str(xAxis.x) + " " + str(xAxis.y) + " " + str(xAxis.z) + " " + str(yAxis.x) + " " + str(yAxis.y) + " " + str(yAxis.z) + " " + ikTarget + ' ' + str(chainLength) + ' \n')
|
||||
|
||||
|
||||
|
||||
elif(ob.type == 'MESH'):
|
||||
skeletonName = '-'
|
||||
@@ -96,21 +95,34 @@ def exportData(ob):
|
||||
file.write(str(vert) + ' ' + str(uv.x) + ' ' + str(uv.y) + ' ' + str(tan.x) + ' ' + str(tan.y) + ' ' + str(tan.z) + ' ' + str(bitan.x) + ' ' + str(bitan.y) + ' ' + str(bitan.z) + ' \n')
|
||||
mesh.free_tangents()
|
||||
|
||||
|
||||
file.write('shapeKeys:\n')
|
||||
if numShapeKeys > 0:
|
||||
print('Exporting shape keys...\n')
|
||||
for shape_key in mesh.shape_keys.key_blocks:
|
||||
if shape_key.name != 'Basis':
|
||||
file.write(shape_key.name + '\n')
|
||||
file.write(shape_key.name + ': ' + str(shape_key.slider_min) + ' ' + str(shape_key.slider_max) + ' \n')
|
||||
for vert in shape_key.data:
|
||||
pos = vert.co
|
||||
file.write(str(pos.x) + ' ' + str(pos.y) + ' ' + str(pos.z) + ' \n')
|
||||
channels.extend(mesh.shape_keys.animation_data.drivers)
|
||||
|
||||
|
||||
file.write('animations: ' + str(numAnims) + '\n')
|
||||
if numAnims > 0:
|
||||
readAnimations(ob, numAnims)
|
||||
|
||||
if ob.animation_data is not None:
|
||||
channels.extend(ob.animation_data.drivers)
|
||||
readDrivers(channels)
|
||||
|
||||
def readDrivers(channels):
|
||||
file.write('drivers: ' + str(len(channels)) + '\n')
|
||||
for channel in channels:
|
||||
firstQuoteId = channel.data_path.find('"') + 1
|
||||
secondQuoteId = channel.data_path.rfind('"')
|
||||
name = (ob.name if firstQuoteId == -1 and secondQuoteId == -1 else channel.data_path[firstQuoteId : secondQuoteId])
|
||||
readDriver(channel, name)
|
||||
|
||||
def getChannelType(channel):
|
||||
channelType = ''
|
||||
|
||||
@@ -125,12 +137,53 @@ def getChannelType(channel):
|
||||
channelType = 'rot_' + coords[arrInd]
|
||||
elif coordType == 'scale':
|
||||
channelType = 'scale_' + coords[arrInd + 1]
|
||||
elif coordType == 'slider_min':
|
||||
channelType = 'shape_key_min'
|
||||
elif coordType == 'value':
|
||||
channelType = 'shape_key_value'
|
||||
elif coordType == 'slider_max':
|
||||
channelType = 'shape_key_max'
|
||||
|
||||
return channelType
|
||||
|
||||
def readChannel(channel):
|
||||
channelType = getChannelType(channel)
|
||||
|
||||
for keyframe in channel.keyframe_points:
|
||||
keyframeId = keyframe.co[0]
|
||||
interp = keyframe.interpolation
|
||||
interpInt = - 1
|
||||
|
||||
if interp == 'CONSTANT':
|
||||
interpInt = 0
|
||||
elif interp == 'LINEAR':
|
||||
interpInt = 1
|
||||
elif interp == 'BEZIER':
|
||||
interpInt = 2
|
||||
|
||||
keyframeValue = keyframe.co[1]
|
||||
file.write(str(keyframeValue) + ' ' + str(keyframeId) + ' ' + str(interpInt))
|
||||
if interp == 'BEZIER':
|
||||
file.write(' ' + str(keyframe.handle_left.x) + ' ' + str(keyframe.handle_left.y) + ' ')
|
||||
file.write(str(keyframe.handle_right.x) + ' ' + str(keyframe.handle_right.y) + ' ')
|
||||
file.write('\n')
|
||||
|
||||
def readDriver(channel, driverName):
|
||||
#for channel in channels:
|
||||
driver = channel.driver
|
||||
target = driver.variables[0].targets[0];
|
||||
|
||||
file.write(target.id.name + ' ' + target.bone_target + ' ' + str(target.transform_type) + ' \n')
|
||||
print('Exporting driver ...\n')
|
||||
|
||||
numKeyframes = len(channel.keyframe_points)
|
||||
channelType = getChannelType(channel)
|
||||
file.write(driverName + ' 1 ' + channelType + ' ' + str(numKeyframes) + ' \n')
|
||||
|
||||
readChannel(channel)
|
||||
|
||||
def readAnimations(ob, numAnims):
|
||||
for nlaStrip in ob.animation_data.nla_tracks[0].strips:
|
||||
start = nlaStrip.frame_start
|
||||
end = nlaStrip.frame_end
|
||||
animName = nlaStrip.name
|
||||
action = bpy.data.actions[animName]
|
||||
numAnimBones = len(action.groups)
|
||||
@@ -152,31 +205,7 @@ def readAnimations(ob, numAnims):
|
||||
file.write('\n')
|
||||
|
||||
for channel in group.channels:
|
||||
channelType = getChannelType(channel)
|
||||
|
||||
dotId = channel.data_path.rfind('.') + 1
|
||||
arrInd = channel.array_index
|
||||
coordType = channel.data_path[dotId :]
|
||||
|
||||
for keyframe in channel.keyframe_points:
|
||||
keyframeId = keyframe.co[0]
|
||||
interp = keyframe.interpolation
|
||||
bpy.context.scene.frame_set(int(start) + int(keyframeId))
|
||||
interpInt = - 1
|
||||
|
||||
if interp == 'CONSTANT':
|
||||
interpInt = 0
|
||||
elif interp == 'LINEAR':
|
||||
interpInt = 1
|
||||
elif interp == 'BEZIER':
|
||||
interpInt = 2
|
||||
|
||||
keyframeValue = keyframe.co[1]
|
||||
file.write(str(keyframeValue) + ' ' + str(keyframeId) + ' ' + str(interpInt))
|
||||
if interp == 'BEZIER':
|
||||
file.write(' ' + str(keyframe.handle_left_type) + ' ' + str(keyframe.handle_left.x) + ' ' + str(keyframe.handle_left.y) + ' ')
|
||||
file.write(str(keyframe.handle_right_type) + ' ' + str(keyframe.handle_right.x) + ' ' + str(keyframe.handle_right.y))
|
||||
file.write('\n')
|
||||
readChannel(channel)
|
||||
|
||||
fl = bpy.data.filepath
|
||||
dotId = 0
|
||||
|
||||
+172
-55
@@ -44,6 +44,7 @@ namespace vb01{
|
||||
}
|
||||
|
||||
connectNodes();
|
||||
setupDrivers();
|
||||
}
|
||||
|
||||
VbModelReader::~VbModelReader(){
|
||||
@@ -104,6 +105,63 @@ namespace vb01{
|
||||
model->attachChild(node);
|
||||
}
|
||||
|
||||
void VbModelReader::setupDrivers(){
|
||||
int i = 0;
|
||||
for(string *data : driverSetups){
|
||||
Skeleton *drivingSkeleton = nullptr, *drivenSkeleton = nullptr;
|
||||
Mesh *drivenMesh = nullptr;
|
||||
|
||||
for(Skeleton *sk : skeletons){
|
||||
if(data[0] == sk->getName())
|
||||
drivingSkeleton = sk;
|
||||
if(data[2] == sk->getName())
|
||||
drivenSkeleton = sk;
|
||||
}
|
||||
for(Mesh *m : meshes)
|
||||
if(data[2] == m->getName())
|
||||
drivenMesh = m;
|
||||
|
||||
Animatable *animatable = nullptr;
|
||||
if(drivenSkeleton){
|
||||
for(Bone *bone : drivenSkeleton->getBones())
|
||||
if(bone->getName() == data[3])
|
||||
animatable = bone;
|
||||
}
|
||||
else if(drivenMesh){
|
||||
int numShapeKeys = drivenMesh->getNumShapeKeys();
|
||||
for(int i = 0; i < numShapeKeys; i++){
|
||||
Mesh::ShapeKey &shapeKey = drivenMesh->getShapeKey(i);
|
||||
if(shapeKey.name == data[3])
|
||||
animatable = &shapeKey;
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(Node *node : nodes)
|
||||
if(node->getName() == data[2])
|
||||
animatable = node;
|
||||
}
|
||||
|
||||
if(drivingSkeleton){
|
||||
for(Bone *bone : drivingSkeleton->getBones())
|
||||
if(bone->getName() == data[1])
|
||||
bone->addDriver(drivers[i]);
|
||||
}
|
||||
else{
|
||||
for(Node *node : nodes)
|
||||
if(node->getName() == data[0])
|
||||
node->addDriver(drivers[i]);
|
||||
}
|
||||
|
||||
KeyframeChannel &keyframeChannel = drivers[i]->getKeyframeChannel();
|
||||
keyframeChannel.animatable = animatable;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
for(string *data : driverSetups)
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
void VbModelReader::createBones(Skeleton *skeleton, vector<string> &skeletonData){
|
||||
map<string, string> ikRelationships;
|
||||
|
||||
@@ -170,8 +228,54 @@ namespace vb01{
|
||||
}
|
||||
}
|
||||
|
||||
void VbModelReader::readAnimations(Animatable *animatable, AnimationController *controller, vector<string> &animationData, int numAnimations){
|
||||
int animStartLine = 0;
|
||||
vector<KeyframeChannel> VbModelReader::readKeyframeChannels(Animatable *animatable, vector<string> &animationData, int &keyframeGroupStartLine){
|
||||
string dataLine[2];
|
||||
getLineData(animationData[keyframeGroupStartLine], dataLine, 2);
|
||||
|
||||
int numKeyframeChannels = atoi(dataLine[1].c_str());
|
||||
string channelData[2 * numKeyframeChannels];
|
||||
getLineData(animationData[keyframeGroupStartLine], channelData, 2 * numKeyframeChannels, 2);
|
||||
|
||||
vector<KeyframeChannel> keyframeChannels;
|
||||
int numTypeKeyframes[numKeyframeChannels];
|
||||
int numKeyframes = 0;
|
||||
for(int k = 0; k < numKeyframeChannels; k++){
|
||||
KeyframeChannel keyframeChannel;
|
||||
|
||||
keyframeChannel.type = KeyframeChannel::getKeyframeChannelType(channelData[2 * k]);
|
||||
numTypeKeyframes[k] = atoi(channelData[2 * k + 1].c_str());
|
||||
numKeyframes += numTypeKeyframes[k];
|
||||
keyframeChannel.animatable = (animatable || !currentSkeleton ? animatable : currentSkeleton->getBone(dataLine[0]));
|
||||
|
||||
keyframeChannels.push_back(keyframeChannel);
|
||||
}
|
||||
|
||||
int keyframeStartLine = keyframeGroupStartLine + 1;
|
||||
int currentChannel = 0, numCurrentTypeKeyframes = 0;
|
||||
for(int k = 0; k < numKeyframes; k++){
|
||||
string keyframeLine = animationData[keyframeStartLine + k];
|
||||
string keyframeData[7];
|
||||
getLineData(keyframeLine, keyframeData, 7);
|
||||
|
||||
Keyframe keyframe;
|
||||
keyframe.value = atof(keyframeData[0].c_str());
|
||||
keyframe.frame = atoi(keyframeData[1].c_str());
|
||||
keyframe.interpolation = (KeyframeInterpolation)atoi(keyframeData[2].c_str());
|
||||
keyframeChannels[currentChannel].keyframes.push_back(keyframe);
|
||||
|
||||
numCurrentTypeKeyframes++;
|
||||
if(numCurrentTypeKeyframes == numTypeKeyframes[currentChannel]){
|
||||
currentChannel++;
|
||||
numCurrentTypeKeyframes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return keyframeChannels;
|
||||
}
|
||||
|
||||
void VbModelReader::readAnimations(Animatable *animatable, AnimationController *controller, vector<string> &animationData){
|
||||
int numAnimations = atoi(animationData[0].substr(animationData[0].find_first_of(':') + 1).c_str());
|
||||
int animStartLine = 1;
|
||||
|
||||
for(int i = 0; i < numAnimations; i++){
|
||||
string animLine = animationData[animStartLine];
|
||||
@@ -184,50 +288,13 @@ namespace vb01{
|
||||
int numKeyframeGroups = atoi(groupsLine.substr(groupsLine.find_first_of(':') + 2).c_str());
|
||||
int keyframeGroupStartLine = animStartLine + 2;
|
||||
for(int j = 0; j < numKeyframeGroups; j++){
|
||||
string dataLine[2];
|
||||
getLineData(animationData[keyframeGroupStartLine], dataLine, 2);
|
||||
|
||||
int numKeyframeChannels = atoi(dataLine[1].c_str());
|
||||
string channelData[2 * numKeyframeChannels];
|
||||
getLineData(animationData[keyframeGroupStartLine], channelData, 2 * numKeyframeChannels, 2);
|
||||
|
||||
vector<KeyframeChannel> keyframeChannels;
|
||||
int numTypeKeyframes[numKeyframeChannels];
|
||||
vector<KeyframeChannel> keyframeChannels = readKeyframeChannels(animatable, animationData, keyframeGroupStartLine);
|
||||
int numKeyframes = 0;
|
||||
for(int k = 0; k < numKeyframeChannels; k++){
|
||||
KeyframeChannel keyframeChannel;
|
||||
|
||||
keyframeChannel.type = Animation::getKeyframeChannelType(channelData[2 * k]);
|
||||
numTypeKeyframes[k] = atoi(channelData[2 * k + 1].c_str());
|
||||
numKeyframes += numTypeKeyframes[k];
|
||||
keyframeChannel.animatable = (animatable ? animatable : currentSkeleton->getBone(dataLine[0]));
|
||||
|
||||
keyframeChannels.push_back(keyframeChannel);
|
||||
for(KeyframeChannel channel : keyframeChannels){
|
||||
animation->addKeyframeChannel(channel);
|
||||
numKeyframes += channel.keyframes.size();
|
||||
}
|
||||
|
||||
int keyframeStartLine = keyframeGroupStartLine + 1;
|
||||
int currentChannel = 0, numCurrentTypeKeyframes = 0;
|
||||
for(int k = 0; k < numKeyframes; k++){
|
||||
string keyframeLine = animationData[keyframeStartLine + k];
|
||||
string keyframeData[9];
|
||||
getLineData(keyframeLine, keyframeData, 9);
|
||||
|
||||
Keyframe keyframe;
|
||||
keyframe.value = atof(keyframeData[0].c_str());
|
||||
keyframe.frame = atoi(keyframeData[1].c_str());
|
||||
keyframe.interpolation = (KeyframeInterpolation)atoi(keyframeData[2].c_str());
|
||||
keyframeChannels[currentChannel].keyframes.push_back(keyframe);
|
||||
|
||||
numCurrentTypeKeyframes++;
|
||||
if(numCurrentTypeKeyframes == numTypeKeyframes[currentChannel]){
|
||||
currentChannel++;
|
||||
numCurrentTypeKeyframes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for(KeyframeChannel ch : keyframeChannels)
|
||||
animation->addKeyframeChannel(ch);
|
||||
|
||||
keyframeGroupStartLine += numKeyframes + 1;
|
||||
}
|
||||
|
||||
@@ -235,6 +302,36 @@ namespace vb01{
|
||||
}
|
||||
}
|
||||
|
||||
void VbModelReader::readDrivers(vector<string> &meshData, string objectName){
|
||||
int numDrivers = atoi(meshData[0].substr(meshData[0].find_first_of(':') + 1).c_str());
|
||||
int driverStartLine = 1;
|
||||
const int numData = 3;
|
||||
|
||||
for(int i = 0; i < numDrivers; i++){
|
||||
string data[numData];
|
||||
getLineData(meshData[driverStartLine], data, numData);
|
||||
bool driverIsBone = (data[numData - 1] != "");
|
||||
Driver::VariableType type = Driver::getDriverVariableType(driverIsBone ? data[numData - 1] : data[numData - 2]);
|
||||
|
||||
int keyframeGroupStartLine = driverStartLine + 1;
|
||||
vector<KeyframeChannel> keyframeChannels = readKeyframeChannels(nullptr, meshData, keyframeGroupStartLine);
|
||||
|
||||
string drivingNode = data[0];
|
||||
string drivingBone = (driverIsBone ? data[1] : "");
|
||||
string drivenAnimatable = objectName;
|
||||
string channelData[1];
|
||||
getLineData(meshData[keyframeGroupStartLine], channelData, 1);
|
||||
string drivenSubAnimatable = channelData[0];
|
||||
|
||||
string *driverSetup = new string[4]{drivingNode, drivingBone, drivenAnimatable, drivenSubAnimatable};
|
||||
driverSetups.push_back(driverSetup);
|
||||
|
||||
drivers.push_back(new Driver(keyframeChannels[0], type));
|
||||
|
||||
driverStartLine += 2 + keyframeChannels[0].keyframes.size();
|
||||
}
|
||||
}
|
||||
|
||||
Skeleton* VbModelReader::readSkeleton(vector<string> &skeletonData){
|
||||
string name = skeletonData[0].substr(getCharId(skeletonData[0], ':') + 2);
|
||||
string line = skeletonData[5];
|
||||
@@ -243,9 +340,13 @@ namespace vb01{
|
||||
|
||||
int boneStartLine = 6;
|
||||
int numBones = atoi(data[1].c_str());
|
||||
|
||||
line = skeletonData[boneStartLine + numBones].substr(getCharId(skeletonData[boneStartLine + numBones], ':') + 2);
|
||||
int numAnimations = atoi(line.c_str());
|
||||
int animationStartLine = boneStartLine + numBones;
|
||||
int driverStartLine = animationStartLine;
|
||||
for(int i = animationStartLine; i < skeletonData.size(); i++)
|
||||
if(skeletonData[i].find_first_of(':') != -1 && skeletonData[i].substr(0, skeletonData[i].length() - 1) == "drivers: "){
|
||||
driverStartLine = i;
|
||||
break;
|
||||
}
|
||||
|
||||
AnimationController *controller = new AnimationController();
|
||||
Skeleton *skeleton = new Skeleton(controller, name);
|
||||
@@ -255,8 +356,12 @@ namespace vb01{
|
||||
createBones(skeleton, skeletonSubData);
|
||||
skeletonSubData.clear();
|
||||
|
||||
skeletonSubData = vector<string>(skeletonData.begin() + (boneStartLine + numBones + 1), skeletonData.end());
|
||||
readAnimations(nullptr, controller, skeletonSubData, numAnimations);
|
||||
skeletonSubData = vector<string>(skeletonData.begin() + animationStartLine, skeletonData.begin() + driverStartLine);
|
||||
readAnimations(nullptr, controller, skeletonSubData);
|
||||
skeletonSubData.clear();
|
||||
|
||||
skeletonSubData = vector<string>(skeletonData.begin() + driverStartLine, skeletonData.end());
|
||||
readDrivers(skeletonSubData, name);
|
||||
skeletonSubData.clear();
|
||||
|
||||
currentSkeleton = nullptr;
|
||||
@@ -355,8 +460,9 @@ namespace vb01{
|
||||
string line = meshData[shapeKeyStartLine];
|
||||
int colonId = line.find_first_of(':');
|
||||
Mesh::ShapeKey shapeKey;
|
||||
shapeKey.name = line.substr(0, colonId);
|
||||
string data[2];
|
||||
getLineData(line.substr(colonId + 1), data, 2);
|
||||
getLineData(line.substr(colonId + 2), data, 2);
|
||||
shapeKey.minValue = atof(data[0].c_str());
|
||||
shapeKey.value = shapeKey.minValue;
|
||||
shapeKey.maxValue = atof(data[1].c_str());
|
||||
@@ -373,9 +479,10 @@ namespace vb01{
|
||||
Vector3 offset = shapeKeyVertPos[vertIds[j]] - vertices[j].pos;
|
||||
vertices[j].shapeKeyOffsets[i] = (offset);
|
||||
}
|
||||
|
||||
delete[] shapeKeyVertPos;
|
||||
shapeKeyStartLine += numVertPos + 1;
|
||||
|
||||
|
||||
shapeKeyStartLine = shapeKeyStartLine + numVertPos + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,6 +515,13 @@ namespace vb01{
|
||||
int vertexStartLine = vertexGroupStartLine + numBones + 1;
|
||||
int faceStartLine = vertexStartLine + numVertices + 1;
|
||||
int shapeKeyStartLine = faceStartLine + numFaces * numVertsPerFace + 1;
|
||||
int animationStartLine = shapeKeyStartLine + numShapes * (1 + numVertices);
|
||||
int driverStartLine = animationStartLine;
|
||||
for(int i = animationStartLine; i < meshData.size(); i++)
|
||||
if(meshData[i].find_first_of(':') != -1 && meshData[i].substr(0, meshData[i].length() - 1) == "drivers: "){
|
||||
driverStartLine = i;
|
||||
break;
|
||||
}
|
||||
|
||||
vector<Vector3> vertPos, vertNorm;
|
||||
vector<float> vertWeights;
|
||||
@@ -440,10 +554,12 @@ namespace vb01{
|
||||
Node *node = new Node(Vector3::VEC_ZERO, Quaternion::QUAT_W, Vector3::VEC_IJK, name, controller);
|
||||
nodes.push_back(node);
|
||||
|
||||
int numAnimLineId = shapeKeyStartLine + numShapes * (1 + numVertices);
|
||||
int numAnimations = atoi(meshData[numAnimLineId].substr(meshData[numAnimLineId].find_first_of(':') + 1).c_str());
|
||||
meshSubData = vector<string>(meshData.begin() + (numAnimLineId + 1), meshData.end());
|
||||
readAnimations(node, controller, meshSubData, numAnimations);
|
||||
meshSubData = vector<string>(meshData.begin() + animationStartLine, meshData.begin() + driverStartLine);
|
||||
readAnimations(node, controller, meshSubData);
|
||||
meshSubData.clear();
|
||||
|
||||
meshSubData = vector<string>(meshData.begin() + driverStartLine, meshData.end());
|
||||
readDrivers(meshSubData, name);
|
||||
meshSubData.clear();
|
||||
|
||||
string skeletonLine = meshData[5];
|
||||
@@ -456,6 +572,7 @@ namespace vb01{
|
||||
skeleton = sk;
|
||||
|
||||
Mesh *mesh = new Mesh(vertices, indices, numFaces, groups, numBones, shapeKeys, numShapes, name);
|
||||
meshes.push_back(mesh);
|
||||
mesh->setSkeleton(skeleton);
|
||||
node->attachMesh(mesh);
|
||||
|
||||
|
||||
+13
-9
@@ -1,19 +1,19 @@
|
||||
#ifndef VB_MODEL_READER
|
||||
#define VB_MODEL_READER
|
||||
|
||||
#include"modelReader.h"
|
||||
#include"util.h"
|
||||
#include"mesh.h"
|
||||
#include "modelReader.h"
|
||||
#include "util.h"
|
||||
#include "mesh.h"
|
||||
|
||||
#include<string>
|
||||
#include<vector>
|
||||
#include<iterator>
|
||||
#include<map>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
|
||||
namespace vb01{
|
||||
class Model;
|
||||
class Node;
|
||||
class Skeleton;
|
||||
class Driver;
|
||||
|
||||
class VbModelReader : public ModelReader{
|
||||
public:
|
||||
@@ -23,19 +23,23 @@ namespace vb01{
|
||||
private:
|
||||
void getObjectBounds(std::map<int, int>&, std::map<int, int>&, std::map<int, int>&);
|
||||
void connectNodes();
|
||||
|
||||
void setupDrivers();
|
||||
void createBones(Skeleton*, std::vector<std::string>&);
|
||||
void readAnimations(Animatable*, AnimationController*, std::vector<std::string>&, int);
|
||||
std::vector<KeyframeChannel> readKeyframeChannels(Animatable*, std::vector<std::string>&, int&);
|
||||
void readAnimations(Animatable*, AnimationController*, std::vector<std::string>&);
|
||||
Skeleton* readSkeleton(std::vector<std::string>&);
|
||||
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>&, Mesh::ShapeKey*, int, int);
|
||||
void readDrivers(std::vector<std::string>&, std::string);
|
||||
void buildMesh(std::vector<std::string>&);
|
||||
Mesh* readMeshes(std::vector<std::string>&);
|
||||
void readLights(std::vector<std::string>&);
|
||||
|
||||
std::vector<Driver*> drivers;
|
||||
std::map<std::string, std::string> relationships;
|
||||
std::vector<std::string*> driverSetups;
|
||||
Skeleton *currentSkeleton = nullptr;
|
||||
std::vector<Skeleton*> skeletons;
|
||||
std::vector<Mesh*> meshes;
|
||||
|
||||
+33
-31
@@ -52,39 +52,40 @@ namespace vb01{
|
||||
skeletonData.push_back("animation: Action");
|
||||
skeletonData.push_back("groups: 2 ");
|
||||
skeletonData.push_back("bipod.L 7 pos_x 2 pos_y 2 pos_z 2 rot_w 2 rot_x 2 rot_y 2 rot_z 2 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("bipod.R 6 pos_x 2 pos_y 2 pos_z 2 rot_w 2 rot_x 2 rot_y 2 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("10 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("10 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("10 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("10 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("10 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("10 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("10 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("10 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("10 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("10 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("10 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("10 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("animation: open");
|
||||
skeletonData.push_back("groups: 1 ");
|
||||
skeletonData.push_back("opening 1 rot_w 2 rot_x 1");
|
||||
skeletonData.push_back("1 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 ");
|
||||
skeletonData.push_back("1 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 10 2 1 1 1 1 ");
|
||||
skeletonData.push_back("0 1 2 1 1 1 1 ");
|
||||
skeletonData.push_back("drivers: 0");
|
||||
}
|
||||
|
||||
void VbModelReaderTest::setupMesh(){
|
||||
@@ -107,7 +108,7 @@ namespace vb01{
|
||||
int numVerts = vertPos.size();
|
||||
int numFaces = numVerts / 3;
|
||||
int numVertexGroups = vertexGroups.size();
|
||||
int numShapeKeys = 0;
|
||||
int numShapeKeys = 1;
|
||||
|
||||
meshData.push_back("MESH: " + meshName);
|
||||
meshData.push_back("pos: 0.0 0.0 0.0");
|
||||
@@ -143,13 +144,14 @@ namespace vb01{
|
||||
meshData.push_back(to_string(i) + " " + uvString + tanString + biTanString);
|
||||
}
|
||||
meshData.push_back("shapeKeys: 0");
|
||||
meshData.push_back("Key 1: 0 1");
|
||||
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");
|
||||
meshData.push_back("drivers: 0");
|
||||
}
|
||||
|
||||
void VbModelReaderTest::testReadSkeletons(){
|
||||
|
||||
Reference in New Issue
Block a user