Jump to content

Merging meshes while still being able to transform each of them


Nesh108
 Share

Recommended Posts

Hello!

I am working on a voxel project and creating a very basic voxel player. It has a box as head, a bigger box for body, etc.

I created the whole thing like this:

        this.player_head = BABYLON.MeshBuilder.CreateBox(PLAYER_HEAD, {size: 1, updatable: true}, scene);
        this.player_body = BABYLON.MeshBuilder.CreateBox(PLAYER_BODY, {width: 1, depth: 0.5, height: 1.5, updatable: true}, scene);
        this.player_right_arm = BABYLON.MeshBuilder.CreateBox(PLAYER_RIGHT_ARM, {width: 0.5, depth: 0.5, height: 1.5, updatable: true}, scene);
        this.player_left_arm = BABYLON.MeshBuilder.CreateBox(PLAYER_LEFT_ARM, {width: 0.5, depth: 0.5, height: 1.5, updatable: true}, scene);
        this.player_right_leg = BABYLON.MeshBuilder.CreateBox(PLAYER_RIGHT_LEG, {width: 0.5, depth: 0.5, height: 1.5, updatable: true}, scene);
        this.player_left_leg = BABYLON.MeshBuilder.CreateBox(PLAYER_LEFT_LEG, {width: 0.5, depth: 0.5, height: 1.5, updatable: true}, scene);

        // Head
        this.player_head.parent = this.player_body;
        this.player_head.position.y += 1.25;

        // Right arm
        this.player_right_arm.parent = this.player_body;
        this.player_right_arm.position.x += 0.75;

        // Left arm
        this.player_left_arm.parent = this.player_body;
        this.player_left_arm.position.x -= 0.75;

        // Right leg
        this.player_right_leg.parent = this.player_body;
        this.player_right_leg.position.x -= 0.25;
        this.player_right_leg.position.y -= 1.5;
        
        // Left leg
        this.player_left_leg.parent = this.player_body;
        this.player_left_leg.position.x += 0.25;
        this.player_left_leg.position.y -= 1.5;

Since I need all the meshes to be treated as a single mesh, I merged them with:

BABYLON.Mesh.MergeMeshes([this.player_head, this.player_body, this.player_right_arm, this.player_left_arm, this.player_left_leg, this.player_right_leg]);

Until here, all beautiful and nice. But a problem arises: I want to be able to move the arms, legs and head to make some sort of animation for walking but it doesn't seem to work.
My player object has the references to all the meshes before the merging, so I thought I would still be able to transform them even after the merging. What's wrong then?

Also, is there perchance a better way to create a bunch of simple meshes, apply a specific material to each of them and then 'merging' them into 1 bigger BABYLON.Mesh without losing their individual texture/material? MergeMeshes destroys the materials of the children objects, which is quite bad :/. 

 

Link to comment
Share on other sites

Beautiful! That looks like it would work.

I gave it a shot and turned it into this:

        this.player = new BABYLON.SolidParticleSystem("Player:SPS", scene);
        this.player.addShape(this.player_head, 1);
        this.player.addShape(this.player_body, 1);
        this.player.addShape(this.player_right_arm, 1);
        this.player.addShape(this.player_left_arm, 1);
        this.player.addShape(this.player_left_leg, 1);
        this.player.addShape(this.player_right_leg, 1);

And then used the mesh by using:

return this.player.buildMesh();

But now the mesh has a very different look (before it looked like a person, now it's all cramped up) and I still cannot change any of the children.

For example I used their reference before being added to the shape:

        this.player_head.rotation.y = Math.sin(time * 1.5) / 3 * this.walkSpeed;
        this.player_head.rotation.z = Math.sin(time) / 2 * this.walkSpeed;

Or should I retrieve it from the SPS? If so, how can I do that?

Link to comment
Share on other sites

nope... updateParticles() is called for each particle and does nothing by default. It's the where you can implement your own behavior (physics, movements, etc)

Anyway, you need to call at least once setParticles() to set the particles from their logical status (what you set here with initParticles() ) to the global mesh vertex positions. If you don't do this, the particles all stay forever in the place where they were built, at the mesh local system origin.

 

Link to comment
Share on other sites

Oh, I see! Thanks, jerome!

Btw, since I am here, is there something like an anchor point for different particles to a specific point (the body)?

This is what I am trying to replicate in Babylon.js: http://danfinlay.com/projects/voxeljs/walk/

And this is what I am currently getting (same formulas): http://www.babylonjs-playground.com/#1ALQPZ#8

It just looks like the meshes should be fixed on one extremity.

Link to comment
Share on other sites

In the SPS system all particles are part of a single mesh, so all are anchored to the centre of the built mesh. So to get the 'person' to walk you can just adjust the position of the mesh.

Example PG http://www.babylonjs-playground.com/#1ALQPZ#9

Since particles are not meshes it is not possible to set a pivot for them nor is it possible to set a parent

However

On 17/03/2017 at 1:25 PM, Nesh108 said:

Also, is there perchance a better way to create a bunch of simple meshes, apply a specific material to each of them and then 'merging' them into 1 bigger BABYLON.Mesh without losing their individual texture/material? MergeMeshes destroys the materials of the children objects, which is quite bad :/. 

you could take a bunch of simple meshes and give them all the same mesh as a parent, then any movement of the parent would move the children.

The other way to consider is using bones and skeletons.

Link to comment
Share on other sites

you could also first translate each model in its local space so it's no longer centered on the system origin, then bake it so the change is integrated in its geometry.

Then only use the modified mesh as a particle model.

Example : a box with a length of L on X could be translated in its local space for L/2 on X. Then baked. The rotation point is still the local space origin, this means the box will rotate like its pivot point would be on its side and no more on its center.

http://doc.babylonjs.com/overviews/how_rotations_and_translations_work#baking-transform

Link to comment
Share on other sites

@jerome 
I think there's something wrong with the SPS actually, it doesn't seem import the pivot of the shapes.
http://www.babylonjs-playground.com/#1ALQPZ#14 that should correctly set pivot of right_arm, but it's still centered.

 

@Nesh108 
Here is a solution, allthough, without SPS. 

// I'll leave fixing the arm rotations to you :P 
http://www.babylonjs-playground.com/#1ALQPZ#13 

Link to comment
Share on other sites

as said formerly, you can always modify the model before inserting in the SPS : if you translate a mesh in its local space, then bake it, it will not be centered any longer. This is the same than changing its pivot point.

Since a solid particle always rotates around its local space origin, this particle built from a locally translated mesh model would then rotate like if its pivot point weren't centered.

Link to comment
Share on other sites

@aWeirdo Ohhh man! That's exactly what I want!! But I just managed to get the SPS up and running, it would be a shame to have to change it again :(

@jerome That sounds like a great way to not have to use bones :D Could show me a small snippet with that? I am not sure I got it as translating the arms didn't change anything. (maybe it's total rubbish): http://www.babylonjs-playground.com/#1ALQPZ#16

 

 

Link to comment
Share on other sites

Well, just define a translation matrix to shift everything for 0.5 down (0, -0.5, 0) a the line 45

Apply then this translation to each model vertices that needs to be shifted down : legs and arms and bake this transformation in the local space with bakeTransformIntoVertices().

Now each shifted model is build 0.5 under the origin in its local space. Its rotation pivot is still the local origin, ok ?

So don't forget to position each particle 0.5 higher than the initial values and here's the result : http://www.babylonjs-playground.com/#1ALQPZ#17

 

[EDIT] btw, it seems all your player members (legs and arms) have the same identical model. So one single model box would be enough imho.

http://www.babylonjs-playground.com/#1ALQPZ#19

Link to comment
Share on other sites

Sweet! That's exactly what I needed! Thanks :)

And yeah, I know they are the same but sometimes I don't mind to have a bit of verbosity if it makes it easier to follow. This is going to be one of the Babylon voxel modules I am going to publish, so I want people to know exactly what to change if they want longer legs or different sized arms :D

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...