SFML

Discuss issues pertaining to the various game/web runtimes of Creature here.
Post Reply
Dmitry
Posts: 1
Joined: Sun Nov 20, 2016 6:53 am

SFML

Post by Dmitry » Sun Dec 18, 2016 6:59 am

Hi. Sorry for my bad Engilish and bear in mind that C++ isn't my language.

I'm trying to use Creature with SFML.
My animation changes opacity of some meshes (like, flash when shooting), but my code always shows all meshes. So, first question: what I need to do for fix it?
And second question: how I can draw without scaling? (pixelart, so I want it was same size as it drawn in texture).

Code: Select all

#include <SFML/Graphics.hpp>
#include "MeshBone.h"
#include "CreatureModule.h"

void Render(CreatureModule::CreatureManager*);
const float delta = 0.001;
const int k = 32;	// zoom factor
const int WindowWidth = 1024;
const int WindowHeight = 768;
const char* file_json = "character_data.json";
const char* file_texture = "character_img.png";

int main()
{
	// Load json
	CreatureModule::CreatureLoadDataPacket json_data;
	CreatureModule::LoadCreatureJSONData(file_json, json_data);

	// Load texture
	sf::Texture texture;
	texture.loadFromFile(file_texture);
	texture.setSmooth(true);

	sf::Sprite sprite;
	sprite.setTexture(texture);

	// Create manager
	auto cur_creature = std::shared_ptr<CreatureModule::Creature>(new CreatureModule::Creature(json_data));
	auto creature_manager = new CreatureModule::CreatureManager(cur_creature);

	// Create animations
	creature_manager->CreateAnimation(json_data, "Shot");
	creature_manager->SetActiveAnimationName("Shot");

	// Create window
	sf::RenderWindow window(sf::VideoMode(WindowWidth, WindowHeight), "Test");

	// Get some info
	auto creature = creature_manager->GetCreature();
	creature->FillRenderColours(255, 255, 255, 255);
	creature_manager->SetIsPlaying(true);
	creature_manager->SetShouldLoop(true);

	auto ptr_pts = creature->GetRenderPts();
	auto ptr_col = creature->GetRenderColours();
	auto ptr_uvs = creature->GetGlobalUvs();
	auto ptr_ind = creature->GetGlobalIndices();

	auto ind_num = creature->GetTotalNumIndices();
	auto pts_num = creature->GetTotalNumPoints();

	sf::VertexArray parts(sf::Triangles, ind_num);

	auto tsize = texture.getSize();
	while (window.isOpen())
	{
		// Input
		sf::Event event;
		while (window.pollEvent(event))
		{
			if ((event.type == sf::Event::Closed)
			|| (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape))
				window.close();
		}
		
		// Update
		creature_manager->Update(delta);

		// Draw
		window.clear(sf::Color::Blue);
		window.draw(sprite);

		for (int i = 0; i < ind_num / 3; i++)
		{
			auto idx1 = ptr_ind[i * 3];
			auto idx2 = ptr_ind[i * 3 + 1];
			auto idx3 = ptr_ind[i * 3 + 2];

			auto point_a_x = ptr_pts[idx1 * 3];
			auto point_a_y = ptr_pts[idx1 * 3 + 1];
			auto point_b_x = ptr_pts[idx2 * 3];
			auto point_b_y = ptr_pts[idx2 * 3 + 1];
			auto point_c_x = ptr_pts[idx3 * 3];
			auto point_c_y = ptr_pts[idx3 * 3 + 1];

			auto a_u = ptr_uvs[idx1 * 2];
			auto a_v = ptr_uvs[idx1 * 2 + 1];
			auto b_u = ptr_uvs[idx2 * 2];
			auto b_v = ptr_uvs[idx2 * 2 + 1];
			auto c_u = ptr_uvs[idx3 * 2];
			auto c_v = ptr_uvs[idx3 * 2 + 1];

			glm::float32 pt1_x = point_a_x * k + WindowWidth / 2;
			glm::float32 pt1_y = WindowHeight / 2 - point_a_y * k;
			parts[i * 3].position = sf::Vector2f(pt1_x, pt1_y);
			glm::float32 pt2_x = point_b_x * k + WindowWidth / 2;
			glm::float32 pt2_y = WindowHeight / 2 - point_b_y * k;
			parts[i * 3 + 1].position = sf::Vector2f(pt2_x, pt2_y);
			glm::float32 pt3_x = point_c_x * k + WindowWidth / 2;
			glm::float32 pt3_y = WindowHeight / 2 - point_c_y * k;
			parts[i * 3 + 2].position = sf::Vector2f(pt3_x, pt3_y);

			parts[i * 3].texCoords = sf::Vector2f(a_u * tsize.x, a_v * tsize.y);
			parts[i * 3 + 1].texCoords = sf::Vector2f(b_u * tsize.x, b_v * tsize.y);
			parts[i * 3 + 2].texCoords = sf::Vector2f(c_u * tsize.x, c_v * tsize.y);
			parts[i * 3].color = sf::Color(ptr_col[idx1 * 4], ptr_col[idx1 * 4 + 1], ptr_col[idx1 * 4 + 2], ptr_col[idx1 * 4 + 3]);
			parts[i * 3 + 1].color = sf::Color(ptr_col[idx2 * 4], ptr_col[idx2 * 4 + 1], ptr_col[idx2 * 4 + 2], ptr_col[idx2 * 4 + 3]);
			parts[i * 3 + 2].color = sf::Color(ptr_col[idx3 * 4], ptr_col[idx3 * 4 + 1], ptr_col[idx3 * 4 + 2], ptr_col[idx3 * 4 + 3]);
		}

		window.draw(parts, &texture);
		window.display();
	}

	return 0;
}

chong
Posts: 693
Joined: Thu Feb 19, 2015 2:21 am

Re: SFML

Post by chong » Sun Dec 18, 2016 5:51 pm

Hello,

The animated opacity values are updated separate from the colours array of the creature character.
Opacity values should be set from the runtime itself, take for example the UE4 runtime code here:

Code: Select all

	
	auto cur_creature = creature_manager->GetCreature();
	auto& regions_map = cur_creature->GetRenderComposition()->getRegionsMap();
	int num_triangles = cur_creature->GetTotalNumIndices() / 3;
	
	// Take Note! regions_alphas is an array with the same size as the number of colours of the character here

	// fill up animation alphas
	for (auto& cur_region_pair : regions_map)
	{
		auto cur_region = cur_region_pair.Value;
		auto start_pt_index = cur_region->getStartPtIndex();
		auto end_pt_index = cur_region->getEndPtIndex();
		auto cur_alpha = FMath::Clamp(cur_region->getOpacity() / 100.0f, 0.0f, 1.0f) * 255.0f;


		for (auto i = start_pt_index; i <= end_pt_index; i++)
		{
			region_alphas[i] = (uint8)cur_alpha;
		}
	}

	// user overwrite alphas
	if (region_alpha_map.Num() > 0)
	{
		// fill up the alphas for specific regions with alpha overwrites
		for (auto cur_iter : region_alpha_map)
		{
			auto cur_name = cur_iter.Key;
			auto cur_alpha = cur_iter.Value;

			if (regions_map.Contains(cur_name))
			{
				meshRenderRegion * cur_region = regions_map[cur_name];
				auto start_pt_index = cur_region->getStartPtIndex();
				auto end_pt_index = cur_region->getEndPtIndex();

				for (auto i = start_pt_index; i <= end_pt_index; i++)
				{
					region_alphas[i] = cur_alpha;
				}
			}
		}
	}

	// now write out alphas into render triangles
	glm::uint32 * cur_idx = cur_creature->GetGlobalIndices();
	for (int i = 0; i < num_triangles; i++)
	{
		int real_idx_1 = cur_idx[0];
		int real_idx_2 = cur_idx[1];
		int real_idx_3 = cur_idx[2];
		auto& cur_tri = draw_tris[i];
		auto set_alpha_1 = region_alphas[real_idx_1];
		auto set_alpha_2 = region_alphas[real_idx_2];
		auto set_alpha_3 = region_alphas[real_idx_3];
		cur_tri.Vertex0.Color = FColor(set_alpha_1, set_alpha_1, set_alpha_1, set_alpha_1);
		cur_tri.Vertex1.Color = FColor(set_alpha_2, set_alpha_2, set_alpha_1, set_alpha_2);
		cur_tri.Vertex2.Color = FColor(set_alpha_3, set_alpha_3, set_alpha_1, set_alpha_3);
		cur_idx += 3;
	}
	

The basic summary I can give you is that you need to retrieve the changing opacity values from each region's getOpacity() method. Then you have an array that is the same size as the colour array in your creature character. You go in for each region and set the alpha/colour based on the opacity value retrieved from each region.

Have a look at the UE4 code for reference, it should make a lot of sense.

With regard to scaling, scaling in Creature is all relative since we are doing mesh/bone skinning here with world space points. You are going to have to set the scaling to a correct value relative to what you want; you can also swap in whatever resolution texture you want for the character since the texture map and character json data are independent of each other.

Cheers

Post Reply