Jump to content

[SOLVED] How to create an ObjectMeshSkinned that moves with a set frame.


photo

Recommended Posts

hello.

I am trying to create an ObjectMeshSkinned that moves or rotates the object's mesh.
The purpose is to create an object of that shape and then export it as an animated fbx.
I am trying to use keyframes.
I want to simply move it to the position of -1 at frame 0 and 1 at frame 1.

int AppWorldLogic::init()
{
	// load a mesh from the file
	MeshPtr mesh = Mesh::create("core/meshes/box.mesh");
	// create a new boundbox for the mesh including new surface
	mesh->createBounds();

	//Appends an animation
	int animation = mesh->addAnimation();

	//Sets the number of animation frames
	mesh->setNumAnimationFrames(0, 2);

	Vector< Math::vec3 > xyz;
	Vector< Math::quat > rot;
	Vector< Math::vec3 > scale;

	xyz.push_back(Math::vec3(-1.0f));
	xyz.push_back(Math::vec3(1.0f));

	//Updates the animation frame 
	mesh->setAnimationFrame(0, 0, xyz, rot, scale);


	Vector< Math::vec3 > rxyz;
	Vector< Math::quat > rrot;
	Vector< Math::vec3 > rscale;
	
	//check animation frame.
	mesh->getAnimationFrame(0, 0, rxyz, rrot, rscale);

	//make new skin mesh
	staticMesh = ObjectMeshSkinned::create(mesh);

	//create layer?
	staticMesh->setLayer(0, true, 0.0f);

	//set animation
	staticMesh->setAnimation(0, 0);

	staticMesh->setLoop(true);

	// Write here code to be called on world initialization: initialize resources for your world scene during the world start.
	return 1;
}
Unigine::ObjectMeshSkinnedPtr staticMesh;

////////////////////////////////////////////////////////////////////////////////
// start of the main loop
////////////////////////////////////////////////////////////////////////////////

int AppWorldLogic::update()
{
	
	int nNumFrame = staticMesh->getNumFrames(0);
	staticMesh->setFrame(0, 0);
	///staticMesh->setFrame(1, Unigine::Game::getTime() * 25.0f);
	// Write here code to be called before updating each render frame: specify all graphics-related functions you want to be called every frame while your application executes.
	return 1;
}

However, something is wrong and the animation doesn't work.
Please tell me which part should be added.
Lastly, this year is just around the corner, and we are very grateful for your support and help. I wish you a good end of the year and Christmas.

Link to comment

Hi KOVIAHN,

Quote

I am trying to create an ObjectMeshSkinned that moves or rotates the object's mesh.

Unfortunately, ObjectMeshSkinned only supports bone-based animation now. Mesh animation is not supported.

Mesh::setAnimationFrame() method is linked to the method Mesh::setAnimationBones().
For example:

Vector<short> bones;
Vector<Math::mat4> frames;

bones.resize(10);
frames.resize(10);

mesh->setAnimationBones(0, bones);
mesh->setNumAnimationFrames(0, 2);

int frame_index = 0; // first frame
frames[0] = ...; // sets first bone position/rotation/scale for the first frame
frames[1] = ...; // sets second bone pos/rot/scale for the first frame
mesh->setAnimationFrame(0, frame_index, frames);

frame_index = 1; // second frame
frames[0] = ...; // sets first bone position/rotation/scale for the second frame
frames[1] = ...; // sets second bone pos/rot/scale for the second frame
mesh->setAnimationFrame(0, frame_index, frames);

The only way to move the object's mesh is the Tracker tool. Or, you can create your own simple animation system.

Best regards,
Alexander

Link to comment

Hi alexander

Thank you for your answer.

I noticed that ObjectMeshSkinned is animated in bone based animation. I also understood implementing a tracker tool and a simple animation system.

But I still have a question.

https://developer.unigine.com/en/docs/2.16.1/api/library/rendering/class.mesh?rlang=cpp#addBone_cstr_int_int

Is it possible to animate after adding a bone to a cube-like mesh where no bone exists through the AddBone function?

I called the function to test the animation, but there is still no response, so I ask.

 

Link to comment
Quote

Is it possible to animate after adding a bone to a cube-like mesh where no bone exists through the AddBone function?

Yeah, you can do that.
But, after adding Mesh::addBone() you need to call these 3 methods for every vertex of your mesh also:

Mesh::setWeightCount(vertex_num, 1, 0);
Mesh::setWeightWeights(vertex_num, ivec4(1), 0);
Mesh::setWeightBones(vertex_num, ivec4(0), 0);

Best regards,
Alexander

Link to comment

Dear alexander :) 

I wish you a happy new year and a good holiday season.

I tried coding after reading the article you wrote above, but it still doesn't work.

int AppWorldLogic::init()
{
	// load a mesh from the file
	MeshPtr mesh = Mesh::create("core/meshes/plane.mesh");
	// create a new boundbox for the mesh including new surface
	mesh->createBounds();


	int nCount = mesh->getNumVertex(0);

	mesh->setNumWeights(4, 0);
	mesh->setWeightCount(0 ,1, 0);

	////Appends an animation
	int animation = mesh->addAnimation();

	int nBone1 = mesh->addBone();
	int nBone2 = mesh->addBone();

	mesh->setBoneTransform(0, (mat4)Math::translate(-0.25,0,0));
	mesh->setBoneTransform(1, (mat4)Math::translate(0.25,0,0));

	//mesh->setNumWeights()

	int VertextCount = mesh->getNumVertex(0);

	Unigine::Math::vec3 v1 = mesh->getVertex(0, 0); //-0.5, -0.5. 0
	Unigine::Math::vec3 v2 = mesh->getVertex(1, 0); //-0.5, 0.5. 0
	Unigine::Math::vec3 v3 = mesh->getVertex(2, 0); //0.5, -0.5. 0
	Unigine::Math::vec3 v4 = mesh->getVertex(3, 0); //0.5, 0.5. 0
	


	int nBones = mesh->getNumBones();
	mesh->setWeightCount(0, 1, 0);
	mesh->setWeightWeights(0, vec4(1.0,0.0, 0, 0), 0);
	mesh->setWeightBones(0, ivec4(0, 0, 0, 0), 0);

	mesh->setWeightWeights(0, Unigine::Math::vec4(1.0f, 0.0, 0.0, 0.0), 0);

	mesh->setWeightCount(1, 1, 0);
	mesh->setWeightWeights(1, vec4(1.0, 0.0, 0, 0), 0);
	mesh->setWeightBones(1, ivec4(0, 0, 0, 0), 0);

	mesh->setWeightWeights(1, Unigine::Math::vec4(1.0f, 0.0, 0.0, 0.0), 0);


	mesh->setWeightCount(2, 1, 0);
	mesh->setWeightWeights(2, vec4(1.0, 0.0, 0, 0), 0);
	mesh->setWeightBones(2, ivec4(1, 0, 0, 0), 0);
	mesh->setWeightWeights(2, Unigine::Math::vec4(1.0f, 0.0, 0.0, 0.0), 0);



	mesh->setWeightCount(3, 1, 0);
	mesh->setWeightWeights(3, vec4(1.0, 0.0, 0, 0), 0);
	mesh->setWeightBones(3, ivec4(1, 0, 0, 0), 0);
	mesh->setWeightWeights(3, Unigine::Math::vec4(1.0f, 0.0, 0.0, 0.0), 0);

	Vector<Math::mat4> frames;
	frames.resize(2);


	mesh->setNumAnimationFrames(0, 2);

	int frame_index = 0; // first frame
	frames[0] = (mat4)Unigine::Math::translate(-0.25, 0, 0); // sets first bone position/rotation/scale for the first frame
	frames[1] = (mat4)Unigine::Math::translate(0.25, 0, 0); // sets first bone position/rotation/scale for the first frame
	mesh->setAnimationFrame(0, frame_index, frames);

	frame_index = 1; // second frame
	frames[0] = (mat4)Unigine::Math::translate(-0.25, 0, 0); // sets first bone position/rotation/scale for the first frame
	frames[1] = (mat4)Unigine::Math::translate(0.7, 0, 0); // sets first bone position/rotation/scale for the first frame
	mesh->setAnimationFrame(0, frame_index, frames);

	staticMesh = ObjectMeshSkinned::create(mesh);
	//set animation

	staticMesh->setPosition(Unigine::Math::Vec3(0.0, 0.0, 1.1));
	staticMesh->setLoop(true);
	staticMesh->play();
	// Write here code to be called on world initialization: initialize resources for your world scene during the world start.
	return 1;
}


This is a really simple code that simply creates two bones on the plane and then animates them.
Please check what part is missing.

Please reply after happy holidays :)

Link to comment
  • 2 weeks later...

Hello! 

everything is correct, but you need to specify which bones to animate:

	int nBone1 = mesh->addBone();
	int nBone2 = mesh->addBone();

//....
	Vector<short> bones;
	bones.append(nBone1);
	bones.append(nBone2);
	mesh->setAnimationBones(0, bones); // only 2 bone will be animated

	Vector<Math::mat4> frames;
	frames.resize(2);

	int num_frames = 60;
	mesh->setNumAnimationFrames(0, num_frames);

	for (int frame_index = 0; frame_index < num_frames; frame_index++)
	{
		frames[0] = (mat4)Unigine::Math::translate(-0.25, 0, 0); 
		frames[1] = (mat4)Unigine::Math::translate(frame_index * 0.02, 0, frame_index* 0.02);
      // here 0 and 1 - it is not bone index. it is index in array of index of bone. (hmm....) 
      // for save memory and not specify transformations for bones that are not involved in the animation.
		mesh->setAnimationFrame(0, frame_index, frames);
	}

 

  • Like 1
Link to comment
  • silent changed the title to [SOLVED] How to create an ObjectMeshSkinned that moves with a set frame.
×
×
  • Create New...