From 84a594e6704df82b89f6e53e414d37a1f51df782 Mon Sep 17 00:00:00 2001 From: devZoGok Date: Tue, 2 Mar 2021 10:20:02 +0200 Subject: [PATCH] drivers reading --- animation.cpp | 25 ----- animation.h | 2 +- driver.cpp | 32 +++++- driver.h | 8 +- keyframeChannel.cpp | 33 ++++++ keyframeChannel.h | 2 + mesh.h | 5 +- model.cpp | 32 +++--- model.h | 6 +- modelReader.h | 4 +- node.cpp | 4 +- node.h | 3 +- script.py | 91 +++++++++++------ vbModelReader.cpp | 227 ++++++++++++++++++++++++++++++++---------- vbModelReader.h | 22 ++-- vbModelReaderTest.cpp | 64 ++++++------ 16 files changed, 378 insertions(+), 182 deletions(-) diff --git a/animation.cpp b/animation.cpp index 1342361..c724716 100644 --- a/animation.cpp +++ b/animation.cpp @@ -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; diff --git a/animation.h b/animation.h index 1bba071..693bd8f 100644 --- a/animation.h +++ b/animation.h @@ -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 getKeyframeChannelsByAnimatable(Animatable*); + inline void addKeyframeChannels(std::vector 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& getKeyframeChannels(){return keyframeChannels;} diff --git a/driver.cpp b/driver.cpp index d9598d7..c9e4867 100644 --- a/driver.cpp +++ b/driver.cpp @@ -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; } } diff --git a/driver.h b/driver.h index eeb0026..110a25e 100644 --- a/driver.h +++ b/driver.h @@ -2,6 +2,7 @@ #define DRIVER #include "keyframeChannel.h" +#include 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; }; diff --git a/keyframeChannel.cpp b/keyframeChannel.cpp index d07ed65..2fdbfd2 100644 --- a/keyframeChannel.cpp +++ b/keyframeChannel.cpp @@ -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++){ diff --git a/keyframeChannel.h b/keyframeChannel.h index 5558d25..08e3c84 100644 --- a/keyframeChannel.h +++ b/keyframeChannel.h @@ -2,6 +2,7 @@ #define KEYFRAME_CHANNEL_H #include +#include namespace vb01{ class Animatable; @@ -33,6 +34,7 @@ namespace vb01{ Animatable *animatable = nullptr; std::vector keyframes; + static KeyframeChannel::Type getKeyframeChannelType(std::string); static float interpolate(float, float, Keyframe::Interpolation, float); static Keyframe findKeyframe(float, KeyframeChannel, bool); static void transform(); diff --git a/mesh.h b/mesh.h index 252dc69..df366bb 100755 --- a/mesh.h +++ b/mesh.h @@ -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(); diff --git a/model.cpp b/model.cpp index 22b65bf..93f7d82 100755 --- a/model.cpp +++ b/model.cpp @@ -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 -#include -#include -#include -#include +#include +#include +#include +#include +#include using namespace std; using namespace Assimp; diff --git a/model.h b/model.h index fc94306..70b1672 100755 --- a/model.h +++ b/model.h @@ -1,9 +1,9 @@ #ifndef MODEL_H #define MODEL_H -#include -#include -#include"node.h" +#include +#include +#include "node.h" class aiScene; class aiNode; diff --git a/modelReader.h b/modelReader.h index 8695c3f..f9992e6 100644 --- a/modelReader.h +++ b/modelReader.h @@ -1,8 +1,8 @@ #ifndef MODEL_READER #define MODEL_READER -#include -#include"model.h" +#include +#include "model.h" namespace vb01{ class ModelReader{ diff --git a/node.cpp b/node.cpp index 0a3c683..b9eb8b0 100755 --- a/node.cpp +++ b/node.cpp @@ -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){ diff --git a/node.h b/node.h index 1eae93f..a3cdfa3 100755 --- a/node.h +++ b/node.h @@ -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, Quaternion, bool); AnimationController *controller = nullptr; - std::vector drivers; + std::vector drivers; protected: virtual void animate(float, KeyframeChannel); virtual float getDriverValue(Driver::VariableType); diff --git a/script.py b/script.py index 956cbed..2c45004 100644 --- a/script.py +++ b/script.py @@ -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 diff --git a/vbModelReader.cpp b/vbModelReader.cpp index 8be24df..0af586b 100644 --- a/vbModelReader.cpp +++ b/vbModelReader.cpp @@ -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 &skeletonData){ map ikRelationships; @@ -170,8 +228,54 @@ namespace vb01{ } } - void VbModelReader::readAnimations(Animatable *animatable, AnimationController *controller, vector &animationData, int numAnimations){ - int animStartLine = 0; + vector VbModelReader::readKeyframeChannels(Animatable *animatable, vector &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 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 &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 keyframeChannels; - int numTypeKeyframes[numKeyframeChannels]; + vector 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 &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 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 &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(skeletonData.begin() + (boneStartLine + numBones + 1), skeletonData.end()); - readAnimations(nullptr, controller, skeletonSubData, numAnimations); + skeletonSubData = vector(skeletonData.begin() + animationStartLine, skeletonData.begin() + driverStartLine); + readAnimations(nullptr, controller, skeletonSubData); + skeletonSubData.clear(); + + skeletonSubData = vector(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 vertPos, vertNorm; vector 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(meshData.begin() + (numAnimLineId + 1), meshData.end()); - readAnimations(node, controller, meshSubData, numAnimations); + meshSubData = vector(meshData.begin() + animationStartLine, meshData.begin() + driverStartLine); + readAnimations(node, controller, meshSubData); + meshSubData.clear(); + + meshSubData = vector(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); diff --git a/vbModelReader.h b/vbModelReader.h index 5b55b1b..238ceb2 100644 --- a/vbModelReader.h +++ b/vbModelReader.h @@ -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 -#include -#include -#include +#include +#include +#include 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&, std::map&, std::map&); void connectNodes(); - + void setupDrivers(); void createBones(Skeleton*, std::vector&); - void readAnimations(Animatable*, AnimationController*, std::vector&, int); + std::vector readKeyframeChannels(Animatable*, std::vector&, int&); + void readAnimations(Animatable*, AnimationController*, std::vector&); Skeleton* readSkeleton(std::vector&); void readVertices(std::vector&, std::vector&, std::vector&, std::vector&, int); void readFaces(std::vector&, std::vector&, std::vector&, std::vector&, std::vector&, int, Mesh::Vertex*, u32*); void readVertexGroups(std::string*, std::vector&, int); void readShapeKeys(Mesh::Vertex*, std::vector&, std::vector&, Mesh::ShapeKey*, int, int); + void readDrivers(std::vector&, std::string); void buildMesh(std::vector&); Mesh* readMeshes(std::vector&); void readLights(std::vector&); + std::vector drivers; std::map relationships; + std::vector driverSetups; Skeleton *currentSkeleton = nullptr; std::vector skeletons; std::vector meshes; diff --git a/vbModelReaderTest.cpp b/vbModelReaderTest.cpp index 334dbaf..2d8ce81 100644 --- a/vbModelReaderTest.cpp +++ b/vbModelReaderTest.cpp @@ -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(){