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 Font::drawText(const ICommandBuffersSP& cmdBuffer, const glm::mat4& viewProjection, const glm::vec2& translate, const std::string& text, const glm::vec4& color) const { if (!cmdBuffer.get()) { return; } // const VkBuffer buffers[1] = {vertexBuffer->getBuffer()->getBuffer()}; VkDeviceSize offsets[1] = {0}; vkCmdBindVertexBuffers(cmdBuffer->getCommandBuffer(), 0, 1, buffers, offsets); // glm::vec2 cursor = translate; const Char* lastCharacter = nullptr; for (auto c : text) { // Line break. if (c == '\n') { cursor.x = translate.x; cursor.y += getLineHeight(); lastCharacter = nullptr; continue; } auto currentCharacter = allCharacters.find((int32_t)c); if (currentCharacter == allCharacters.end()) { // Character not found. lastCharacter = nullptr; continue; } // // Advance, depending on kerning of current and last character. // if (lastCharacter) { cursor.x += lastCharacter->getKerning(currentCharacter->second.getId()); } // // Get bottom left corner of the character texture. // glm::vec2 origin = cursor; origin.y += getBase(); origin.x -= currentCharacter->second.getXoffset(); // Draw Character. glm::mat4 transformVertex = viewProjection * translateMat4(origin.x, origin.y, 0.0f); vkCmdPushConstants(cmdBuffer->getCommandBuffer(), graphicsPipeline->getLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 16, glm::value_ptr(transformVertex)); glm::mat3 translateTexCoord = translateMat3(currentCharacter->second.getX() / getScaleWidth(), (getScaleHeight() - currentCharacter->second.getY() - currentCharacter->second.getHeight()) / getScaleHeight()); glm::mat3 scaleTexCoord = scaleMat3(currentCharacter->second.getWidth() / getScaleWidth(), currentCharacter->second.getHeight() / getScaleHeight(), 1.0f); glm::mat3 transformTexCoord = translateTexCoord * scaleTexCoord; vkCmdPushConstants(cmdBuffer->getCommandBuffer(), graphicsPipeline->getLayout(), VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 16, sizeof(float) * 9, glm::value_ptr(transformTexCoord)); vkCmdPushConstants(cmdBuffer->getCommandBuffer(), graphicsPipeline->getLayout(), VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 16 + sizeof(float) * 12, sizeof(float) * 4, glm::value_ptr(color)); // Expecting triangle strip as primitive topology. vkCmdDraw(cmdBuffer->getCommandBuffer(), 4, 1, 0, 0); // // Advance, as character has been drawn. // cursor.x += currentCharacter->second.getXadvance(); lastCharacter = ¤tCharacter->second; } }
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; }