Beispiel #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();
}
Beispiel #2
0
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 = &currentCharacter->second;
	}
}
Beispiel #3
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;
}