Jump to content

[SOLVED] FBX Import Animation(Importing Models Directly to Memory)


photo

Recommended Posts

Hello
First of all, thank you for providing such a great sample.

//Importing Models Directly to Memory
https://developer.unigine.com/en/docs/2.13/code/usage/custom_import_processor/index?rlang=cpp

I have a question.

Through the Importing Models Directly to Memory method, an accurate mesh shape could be imported. But the part about animation import is not at all
I didn't know...

Is there no separate guide document??

I am attaching a simple sample project that I am currently testing.

FBXAnimation.zip

Edited by bboguni
Link to comment

Hello!
This is an updated MemoryProcessor:

class MemoryProcessor : public Unigine::ImportProcessor
{
protected:
	// method to be called on mesh processing
	virtual bool onProcessMesh(MeshPtr &mesh, ImportMesh *import_mesh) override
	{
		UGUID guid;
		guid.generate();
		import_mesh->filepath = guid.getString();
		meshes.append(import_mesh->filepath, mesh);
		return true;
	}

	// method to be called on mesh animation processing
	bool onProcessAnimation(MeshPtr& animation, ImportMesh* import_mesh, ImportAnimation* import_animation) override
	{
		UGUID guid;
		guid.generate();
		meshes_animations.append(import_mesh, animation);
		return true;
	}

	bool onProcessAnimation(MeshPtr& animation, ImportAnimation* import_animation)
	{
		UGUID guid;
		guid.generate();

		return true;
	}

	// method to be called on texture processing
	bool onProcessTexture(ImportTexture *import_texture)
	{
		import_texture->filepath = import_texture->original_filepath;
		return true;
	}

	// method to be called on material processing
	bool onProcessMaterial(MaterialPtr &material, ImportMaterial *import_material)
	{
		UGUID guid;
		guid.generate();
		materials.append(import_material->name, material);
		return true;
	}

	// method performing nodeto be called on mesh processing
	void convert_node(NodePtr &node, ImportNode *import_node)
	{
		using namespace Unigine::Math;

		// checking node's type and performing the corresponding import operations
		if (import_node->camera != nullptr)
		{
			// importing a camera
			PlayerPtr player;
			getImporter()->importCamera(this, player, import_node->camera);
			node = player;
			node->setWorldTransform(Mat4(import_node->transform));
		}
		else if (import_node->light != nullptr)
		{
			// importing a camera
			LightPtr light;
			getImporter()->importLight(this, light, import_node->light);
			node = light;
			node->setWorldTransform(Mat4(import_node->transform));
		}
		else if (import_node->mesh != nullptr)
		{
			// importing a mesh
			ImportMesh* import_mesh = import_node->mesh;

			if (import_mesh->has_animations)
			{
				float fps = getImporter()->getParameterFloat("fps");
				ObjectMeshSkinnedPtr SkinObject = ObjectMeshSkinned::create(meshes[import_mesh->filepath]);
				auto it = meshes_animations.find(import_mesh);
				if (it != meshes_animations.end())
				{
					int animation_id = SkinObject->addAnimation(it->data);
					SkinObject->setNumLayers(1);
					SkinObject->setAnimation(0, animation_id);
				}
				SkinObject->setSpeed(fps);
				//SkinObject->setWorldTransform(Mat4(import_node->transform));
				//
				for (const ImportGeometry& geometry : import_mesh->geometries)
				{
					for (const ImportSurface& surface : geometry.surfaces)
					{
						int surface_index = surface.target_surface;
						if (surface_index == -1)
						{
							Log::error("Can't find surface \"%s\".\n", surface.name.get());
							continue;
						}
						if (surface.material == nullptr)
							continue;

						SkinObject->setMaterial(materials[surface.material->name], surface_index);
					}
				}
				node = SkinObject;
				//for test
				SkinObject->setLoop(true);
				SkinObject->play();
			}
			else
			{
				ObjectMeshStaticPtr object = ObjectMeshStatic::create(meshes[import_mesh->filepath]);
				object->setWorldTransform(Mat4(import_node->transform));

				for (const ImportGeometry& geometry : import_mesh->geometries)
				{
					for (const ImportSurface& surface : geometry.surfaces)
					{
						int surface_index = surface.target_surface;
						if (surface_index == -1)
						{
							Log::error("Can't find surface \"%s\".\n", surface.name.get());
							continue;
						}
						if (surface.material == nullptr)
							continue;

						object->setMaterial(materials[surface.material->name], surface_index);
					}
				}

				node = object;
			}
		}
		else
		{
			// or importing a dummy node
			node = NodeDummy::create();
			node->setWorldTransform(Mat4(import_node->transform));
		}

		node->setName(import_node->name);

		// recursively processing all node's children and adding them to the hierarchy in the world
		for (ImportNode *import_child : import_node->children)
		{
			NodePtr child;
			convert_node(child, import_child);
			node->addWorldChild(child);
		}
	}

	// method to be called on node processing
	virtual bool onProcessNode(NodePtr &node, ImportNode *import_node)
	{
		convert_node(node, import_node);
		return true;
	}

private:
	// HashMaps to be used for imported meshes and materials
	HashMap<String, MeshPtr> meshes;
	HashMap<ImportMesh *, MeshPtr> meshes_animations;
	HashMap<String, Unigine::MaterialPtr> materials;
};

it is also necessary to update the code in import methods:
 

MemoryProcessor memory_processor;
ImportScene* scene = importer->getScene();
for (ImportMesh* meshToImport : scene->getMeshes())
{
	MeshPtr m = Mesh::create();
	importer->importMesh(&memory_processor, m, meshToImport);
	if (m->getNumBones())
	{
		for (ImportAnimation* animation : scene->getAnimations())
		{
			MeshPtr animation_mesh = Mesh::create(); //mesh for animation
			importer->importAnimation(&memory_processor, animation_mesh, meshToImport, animation);
		}
	}
}
  • Like 2
Link to comment
  • bboguni changed the title to [SOLVED]FBX Import Animation(Importing Models Directly to Memory)
  • silent changed the title to [SOLVED] FBX Import Animation(Importing Models Directly to Memory)
×
×
  • Create New...