Aabb::Aabb(const glm::vec3& translate, const glm::vec3& scale) : corners(), asObb(), asSphere() { glm::mat4 transfom = translateMat4(translate.x, translate.y, translate.z) * scaleMat4(scale.x, scale.y, scale.z); for (int32_t i = 0; i < 2; i++) { corners[i] = transfom * cornersUnit[i]; } calculateObb(); calculateSphere(); }
void Node::updateRecursive(const IUpdateThreadContext& updateContext, const glm::mat4& parentTransformMatrix, const VkBool32 parentTransformMatrixDirty, const glm::mat4& parentBindMatrix, const VkBool32 parentBindMatrixDirty, const INodeSP& armatureNode) { transformMatrixDirty = transformMatrixDirty || parentTransformMatrixDirty; bindMatrixDirty = bindMatrixDirty || parentBindMatrixDirty; auto newArmatureNode = (joints != 0) ? INode::shared_from_this() : armatureNode; if (currentAnimation >= 0 && currentAnimation < (int32_t) allAnimations.size()) { currentTime += (float) updateContext.getDeltaTime(); if (currentTime < allAnimations[currentAnimation]->getStart() || currentTime > allAnimations[currentAnimation]->getStop()) { currentTime = allAnimations[currentAnimation]->getStart(); } const auto& currentChannels = allAnimations[currentAnimation]->getChannels(); float value; // quat quaternion; VkBool32 quaternionDirty = VK_FALSE; // for (size_t i = 0; i < currentChannels.size(); i++) { value = interpolate(currentTime, currentChannels[i]); if (currentChannels[i]->getTargetTransform() == VKTS_TARGET_TRANSFORM_TRANSLATE) { translate[currentChannels[i]->getTargetTransformElement()] = value; } else if (currentChannels[i]->getTargetTransform() == VKTS_TARGET_TRANSFORM_ROTATE) { rotate[currentChannels[i]->getTargetTransformElement()] = value; } else if (currentChannels[i]->getTargetTransform() == VKTS_TARGET_TRANSFORM_QUATERNION_ROTATE) { switch (currentChannels[i]->getTargetTransformElement()) { case VKTS_TARGET_TRANSFORM_ELEMENT_X: quaternion.x = value; break; case VKTS_TARGET_TRANSFORM_ELEMENT_Y: quaternion.y = value; break; case VKTS_TARGET_TRANSFORM_ELEMENT_Z: quaternion.z = value; break; case VKTS_TARGET_TRANSFORM_ELEMENT_W: quaternion.w = value; break; } quaternionDirty = VK_TRUE; } else if (currentChannels[i]->getTargetTransform() == VKTS_TARGET_TRANSFORM_SCALE) { scale[currentChannels[i]->getTargetTransformElement()] = value; } } if (quaternionDirty) { rotate = quaternion.rotation(); } // transformMatrixDirty = VK_TRUE; if (joints != 0) { bindMatrixDirty = VK_TRUE; } } // if (bindMatrixDirty) { // Only armature, having joints not zero and joints can enter here. glm::mat4 localBindMatrix; if (joints == 0) { localBindMatrix = translateMat4(bindTranslate.x, bindTranslate.y, bindTranslate.z) * rotateRzRyRxMat4(bindRotate.z, bindRotate.y, bindRotate.x) * scaleMat4(bindScale.x, bindScale.y, bindScale.z); } else { // Armature has no bind values, but transform is taken into account. localBindMatrix = translateMat4(translate.x, translate.y, translate.z) * rotateRzRyRxMat4(rotate.z, rotate.y, rotate.x) * scaleMat4(scale.x, scale.y, scale.z); } this->bindMatrix = parentBindMatrix * localBindMatrix; this->inverseBindMatrix = glm::inverse(this->bindMatrix); // transformMatrixDirty = VK_TRUE; } // if (transformMatrixDirty) { if (jointIndex == -1) { this->transformMatrix = translateMat4(translate.x, translate.y, translate.z) * rotateRzRyRxMat4(rotate.z, rotate.y, rotate.x) * scaleMat4(scale.x, scale.y, scale.z); // Only use parent transform, if this is not an armature. if (joints == 0) { this->transformMatrix = parentTransformMatrix * this->transformMatrix; } } else { // Processing joints. this->transformMatrix = bindMatrix * translateMat4(translate.x, translate.y, translate.z) * rotateRzRyRxMat4(rotate.z, rotate.y, rotate.x) * scaleMat4(scale.x, scale.y, scale.z) * this->inverseBindMatrix; // Only use parent transform, if parent is not an armature. if (parentNode.get() && parentNode->getNumberJoints() == 0) { this->transformMatrix = parentTransformMatrix * this->transformMatrix; } } // Update buffer. if (allMeshes.size() > 0) { transformUniformBuffer->upload(0, 0, this->transformMatrix); auto transformNormalMatrix = glm::transpose(glm::inverse(glm::mat3(this->transformMatrix))); transformUniformBuffer->upload(sizeof(float) * 16, 0, transformNormalMatrix); } else if (joints != 0) { // If this is an armature, store the parent matrix. // This allows to modify the parent matrices without recalculating the bind matrices. jointsUniformBuffer->upload(0, 0, parentTransformMatrix); auto transformNormalMatrix = glm::transpose(glm::inverse(glm::mat3(parentTransformMatrix))); jointsUniformBuffer->upload(sizeof(float) * 16, 0, transformNormalMatrix); } else if (jointIndex >= 0 && jointIndex < VKTS_MAX_JOINTS) { if (newArmatureNode.get()) { auto currentJointsUniformBuffer = newArmatureNode->getJointsUniformBuffer(); if (currentJointsUniformBuffer.get()) { // Upload the joint matrices to blend them on the GPU. size_t offset = sizeof(float) * 16 + sizeof(float) * 12; currentJointsUniformBuffer->upload(offset + jointIndex * sizeof(float) * 16, 0, this->transformMatrix); auto transformNormalMatrix = glm::transpose(glm::inverse(glm::mat3(this->transformMatrix))); currentJointsUniformBuffer->upload(offset + VKTS_MAX_JOINTS * sizeof(float) * 16 + jointIndex * sizeof(float) * 12, 0, transformNormalMatrix); } } } else if (jointIndex >= VKTS_MAX_JOINTS) { logPrint(VKTS_LOG_ERROR, "Node: Too many joints: %d >= %d", jointIndex, VKTS_MAX_JOINTS); return; } } for (size_t i = 0; i < allChildNodes.size(); i++) { allChildNodes[i]->updateRecursive(updateContext, this->transformMatrix, this->transformMatrixDirty, this->bindMatrix, this->bindMatrixDirty, newArmatureNode); } // transformMatrixDirty = VK_FALSE; bindMatrixDirty = VK_FALSE; }