Fix the assertions in the AnimationState, optimize code.
parent
a59e1d2a82
commit
f0aee0d952
|
@ -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};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 {};
|
||||
|
|
|
@ -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)))
|
||||
}
|
||||
})
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue