Example #1
0
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();
}
Example #2
0
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;
}