Fix the assertions in the AnimationState, optimize code.

master
Nicole Collings 2020-04-06 19:17:16 -07:00
parent a59e1d2a82
commit f0aee0d952
6 changed files with 54 additions and 127 deletions

View File

@ -63,6 +63,6 @@ double AnimationState::getFrame() {
return currentFrame;
}
std::tuple<unsigned int, unsigned int> AnimationState::getBounds() {
return std::make_tuple(startFrame, endFrame);
glm::ivec2 AnimationState::getBounds() {
return {startFrame, endFrame};
}

View File

@ -25,7 +25,7 @@ public:
void setFrame(double frame);
double getFrame();
std::tuple<unsigned int, unsigned int> getBounds();
glm::ivec2 getBounds();
private:
std::map<std::string, AnimationSegment> animations;

View File

@ -50,7 +50,7 @@ int Model::fromSerialized(const SerializedModel& model, const std::vector<std::s
return 0;
}
void Model::getTransformsByFrame(double frame, std::tuple<unsigned int, unsigned int> bounds, std::vector<glm::mat4>& transforms) {
void Model::getTransformsByFrame(double frame, glm::ivec2 bounds, std::vector<glm::mat4>& transforms) {
transforms.resize(bones.size());
if (!rootBones.empty())
@ -215,98 +215,37 @@ void Model::calcBoneHeirarchy(aiNode *node, const aiScene *scene, int parentBone
}
}
for (unsigned int i = 0; i < node->mNumChildren; i++) {
calcBoneHeirarchy(node->mChildren[i], scene, index);
}
for (unsigned int i = 0; i < node->mNumChildren; i++) calcBoneHeirarchy(node->mChildren[i], scene, index);
}
void Model::calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, std::tuple<unsigned int, unsigned int> bounds, std::vector<glm::mat4>& transforms) {
void Model::calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, glm::ivec2 bounds, std::vector<glm::mat4>& transforms) {
AnimChannel* channel = nullptr;
for (auto &i : animation.channels) {
if (i.index == bone.index) channel = &i;
if (i.index == bone.index) {
channel = &i;
break;
}
}
glm::mat4 boneTransformation(1.0f);
if (channel) {
glm::vec3 scale;
calcInterpolatedScale(scale, animTime, bone, *channel, bounds);
glm::mat4 scaleMat = glm::scale(glm::mat4(1.0), scale);
glm::mat4 position = glm::translate(glm::mat4(1.0), calcBoneVal<glm::vec3>(animTime, bounds, channel->positionKeys, {},
[](const glm::vec3 &a, const glm::vec3 &b, float factor) { return glm::mix(a, b, factor); }));
glm::mat4 scale = glm::scale(glm::mat4(1.0), calcBoneVal<glm::vec3>(animTime, bounds, channel->scaleKeys, {},
[](const glm::vec3 &a, const glm::vec3 &b, float factor) { return glm::mix(a, b, factor); }));
glm::mat4 rotation = glm::transpose(glm::mat4(MatConv::AiToGLMMat3(
calcBoneVal<aiQuaternion>(animTime, bounds, channel->rotationKeys, {},
[](const aiQuaternion& a, const aiQuaternion& b, float factor) {
aiQuaternion result;
aiQuaternion::Interpolate(result, a, b, factor);
return result.Normalize();
}).GetMatrix())));
aiQuaternion rotation;
calcInterpolatedRotation(rotation, animTime, bone, *channel, bounds);
glm::mat4 rotationMat = glm::transpose(glm::mat4(MatConv::AiToGLMMat3(rotation.GetMatrix())));
glm::vec3 position;
calcInterpolatedPosition(position, animTime, bone, *channel, bounds);
glm::mat4 positionMat = glm::translate(glm::mat4(1.0), position);
boneTransformation = positionMat * rotationMat * scaleMat;
boneTransformation = position * rotation * scale;
}
glm::mat4 globalTransformation = parentTransform * boneTransformation;
transforms[bone.index] = globalInverseTransform * globalTransformation * bone.offsetMatrix;
for (auto& child : bone.children) {
calcBoneTransformation(animTime, *child, globalTransformation, bounds, transforms);
}
}
void Model::calcInterpolatedPosition(glm::vec3 &position, double animTime, ModelBone& bone, AnimChannel& channel, std::tuple<unsigned int, unsigned int> bounds) {
if (channel.positionKeys.empty()) { position = glm::vec3(0); return; }
if (channel.positionKeys.size() == 1) { position = channel.positionKeys[0].second; return; }
unsigned int index = findPositionIndex(animTime, channel);
unsigned int nextIndex = index + 1;
assert(nextIndex < channel.positionKeys.size());
double delta = channel.positionKeys[nextIndex].first - channel.positionKeys[index].first;
double factor = (animTime - channel.positionKeys[index].first) / delta;
if (nextIndex >= std::get<1>(bounds)) factor = 0;
assert(factor >= 0 && factor <= 1);
glm::vec3 startPosition = channel.positionKeys[index].second;
glm::vec3 endPosition = channel.positionKeys[nextIndex].second;
position = glm::mix(startPosition, endPosition, factor);
}
void Model::calcInterpolatedRotation(aiQuaternion &rotation, double animTime, ModelBone& bone, AnimChannel& channel, std::tuple<unsigned int, unsigned int> bounds) {
if (channel.rotationKeys.empty()) { return; }
if (channel.rotationKeys.size() == 1) { rotation = channel.rotationKeys[0].second; return; }
unsigned int index = findRotationIndex(animTime, channel);
unsigned int nextIndex = index + 1;
assert(nextIndex < channel.rotationKeys.size());
double delta = channel.rotationKeys[nextIndex].first - channel.rotationKeys[index].first;
double factor = (animTime - channel.rotationKeys[index].first) / delta;
if (nextIndex >= std::get<1>(bounds)) factor = 0;
assert(factor >= 0 && factor <= 1);
const aiQuaternion& startRotation = channel.rotationKeys[index].second;
const aiQuaternion& endRotation = channel.rotationKeys[nextIndex].second;
aiQuaternion::Interpolate(rotation, startRotation, endRotation, factor);
rotation = rotation.Normalize();
}
void Model::calcInterpolatedScale(glm::vec3 &scale, double animTime, ModelBone& bone, AnimChannel& channel, std::tuple<unsigned int, unsigned int> bounds) {
if (channel.scaleKeys.empty()) { scale = glm::vec3(1); return; }
if (channel.scaleKeys.size() == 1) { scale = channel.scaleKeys[0].second; return; }
unsigned int index = findScaleIndex(animTime, channel);
unsigned int nextIndex = index + 1;
assert(nextIndex < channel.scaleKeys.size());
double delta = channel.scaleKeys[nextIndex].first - channel.scaleKeys[index].first;
double factor = (animTime - channel.scaleKeys[index].first) / delta;
if (nextIndex >= std::get<1>(bounds)) factor = 0;
assert(factor >= 0 && factor <= 1);
glm::vec3 startScale = channel.scaleKeys[index].second;
glm::vec3 endScale = channel.scaleKeys[nextIndex].second;
scale = glm::mix(startScale, endScale, factor);
for (auto& child : bone.children) calcBoneTransformation(animTime, *child, globalTransformation, bounds, transforms);
}

View File

@ -28,7 +28,7 @@ public:
int fromFile(const std::string &path, const std::vector<std::shared_ptr<AtlasRef>> &texture);
int fromSerialized(const SerializedModel &model, const std::vector<std::shared_ptr<AtlasRef>> &texture);
void getTransformsByFrame(double frame, std::tuple<unsigned int, unsigned int> bounds, std::vector<glm::mat4>& transforms);
void getTransformsByFrame(double frame, glm::ivec2 bounds, std::vector<glm::mat4>& transforms);
// void getTransformsByTime(double time, std::tuple<uint> bounds, std::vector<glm::mat4>& transforms);
const ModelAnimation& getAnimation();
@ -40,31 +40,31 @@ private:
void loadAnimations(const aiScene *scene);
void calcBoneHeirarchy(aiNode *node, const aiScene *scene, int parentBoneIndex);
void calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, std::tuple<unsigned int, unsigned int> bounds, std::vector<glm::mat4>& transforms);
void calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, glm::ivec2 bounds, std::vector<glm::mat4>& transforms);
void calcInterpolatedPosition(glm::vec3& position, double animTime, ModelBone& bone, AnimChannel& channel, std::tuple<unsigned int, unsigned int> bounds);
void calcInterpolatedRotation(aiQuaternion& rotation, double animTime, ModelBone& bone, AnimChannel& channel, std::tuple<unsigned int, unsigned int> bounds);
void calcInterpolatedScale(glm::vec3& scale, double animTime, ModelBone& bone, AnimChannel& channel, std::tuple<unsigned int, unsigned int> bounds);
template <typename T> static inline T calcBoneVal(
double animTime, glm::ivec2 bounds, const std::vector<std::pair<double, T>>& keysArray,
const T& def, std::function<T(const T& a, const T& b, float factor)> merge) {
static inline unsigned int findPositionIndex(double animTime, AnimChannel &channel) {
for (unsigned int i = 1; i < channel.positionKeys.size(); i++) {
if (channel.positionKeys[i].first > animTime) return i - 1;
if (keysArray.empty()) return def;
if (keysArray.size() == 1) return keysArray[0].second;
unsigned int index = 0;
for (unsigned int i = 1; i < keysArray.size(); i++) {
if (keysArray[i].first > animTime) {
index = i - 1;
break;
}
}
assert(false);
}
static inline unsigned int findRotationIndex(double animTime, AnimChannel &channel) {
for (unsigned int i = 1; i < channel.rotationKeys.size(); i++) {
if (channel.rotationKeys[i].first > animTime) return i - 1;
float factor = 1;
unsigned int nextIndex = index + 1;
if (nextIndex >= keysArray.size() || nextIndex > bounds.y) nextIndex = bounds.x;
else {
double delta = keysArray[nextIndex].first - keysArray[index].first;
factor = (animTime - keysArray[index].first) / delta;
}
assert(false);
}
static inline unsigned int findScaleIndex(double animTime, AnimChannel &channel) {
for (unsigned int i = 1; i < channel.scaleKeys.size(); i++) {
if (channel.scaleKeys[i].first > animTime) return i - 1;
}
assert(false);
return merge(keysArray[index].second, keysArray[nextIndex].second, factor);
}
ModelAnimation animation {};

View File

@ -5,21 +5,17 @@ zepha.register_entity("zeus:default:bee", {
display_object = "zeus:default:bee",
display_texture = "zeus:default:bee",
on_create = fn(self) {
on_create = (self) => {
self.object.scale = 1/12
self.object.anims:define({
fly = {1, 45}
})
self.object.anims:set_anim("fly"):play()
},
on_update = fn(self, delta) {
self.object.pos = v(
self.object.pos.x + 0.03 * math.sin(math.rad(self.object.yaw + 90)),
self.object.pos.y,
self.object.pos.z + 0.03 * math.cos(math.rad(self.object.yaw + 90))
)
on_update = (self, delta) => {
self.object.pos = self.object.pos +
V(0.03 * math.sin(math.rad(self.object.yaw + 90)), 0, 0.03 * math.cos(math.rad(self.object.yaw + 90)))
self.object.yaw += 2
}
})
@ -27,7 +23,7 @@ zepha.register_entity("zeus:default:bee", {
zepha.register_keybind("zeus:default:spawn_bee", {
description = "Spawn Bee",
default = zepha.keys.b,
on_press = fn() {
zepha.add_entity("zeus:default:bee", vector.add(zepha.player.pos, v(0, 1.7, 0)))
on_press = () => {
zepha.add_entity("zeus:default:bee", vector.add(zepha.player.pos, V(0, 1.7, 0)))
}
})

View File

@ -30,12 +30,8 @@ zepha.register_entity("zeus:default:rabbit", {
}
if (self.targeting) {
self.object.pos = v(
self.object.pos.x + 0.08 * math.sin(math.rad(self.object.yaw)),
self.object.pos.y,
self.object.pos.z + 0.08 * math.cos(math.rad(self.object.yaw))
)
self.object.pos = self.object.pos +
V(0.08 * math.sin(math.rad(self.object.yaw)), 0, 0.08 * math.cos(math.rad(self.object.yaw)))
self.object.yaw = math.deg(math.atan2(zepha.player.pos.x - self.object.pos.x, zepha.player.pos.z - self.object.pos.z))
}
}
@ -49,12 +45,8 @@ zepha.register_entity("zeus:default:rabbit", {
}
if (self.targeting) {
self.object.pos = v(
self.object.pos.x + 0.08 * math.sin(math.rad(self.object.yaw)),
self.object.pos.y,
self.object.pos.z + 0.08 * math.cos(math.rad(self.object.yaw))
)
self.object.pos = self.object.pos +
V(0.08 * math.sin(math.rad(self.object.yaw)), 0, 0.08 * math.cos(math.rad(self.object.yaw)))
self.object.yaw = math.deg(math.atan2(zepha.player.pos.x - self.object.pos.x, zepha.player.pos.z - self.object.pos.z)) + 180
}
else {