Sign in to follow this  
alexoy

Issues with instances created in Blender

Recommended Posts

Hi all!

I use Blender for modelling. I've found out that mesh's instances can greatly improve performance, however I've got 2 issues after importing scene in Babylon.js:

1. There are no collisions with any instances except "parent" mesh. In Blender collision checkbox is set and affects all instances (no chance to set it separately, but that's OK in this case). How to enable collisions?

2. There are no tags for individual instance. I can set them for "parent" mesh, in Blender tags are visible for all instances, however they are not accessible from Babylon.js. How to set different tags for individual instance?

 

Thank you!

Share this post


Link to post
Share on other sites

I've tried to repeat the same thing on playground with a very basic scene - https://playground.babylonjs.com/#NKZ8CX

Ok, both boxes have collisions :) so probably a problem on my side somewhere.

But still something strange with tags:

- initially I've applied tag to the mesh "Cube", not "Cube.001", which is an instance;

- console shows that tag exists only for "Cube.001". That means, that random mesh/instance gets my tags - how do I use it later?!

 

Could you please make, that we can set tags for instances independently? So any instance can have it's own tags.

 

EDIT ABOUT COLLISIONS:

Collisions disappear when a parent mesh is joined from multiple meshes with different materials.

Share this post


Link to post
Share on other sites

First, when a .babylon file is loaded any tags found in a mesh are applied to any instances.  Currently, there are no unique tags for instances supported in this format.  They look like they are supposed to be copied from the original mesh.  I could grey out adding them in the Blender interface (along with other stuff), but that is not going to help you.

I remember an issue last July with instances & collisions.  The code has move repos since then, so I do not have the commit.  There is code to export an instance's imposter if found.  It does need to be set on each instance.

class MeshInstance:
     def __init__(self, instancedMesh, rotation, rotationQuaternion):
        self.name = instancedMesh.name
        if hasattr(instancedMesh, 'parentId'): self.parentId = instancedMesh.parentId
        self.position = instancedMesh.position
        if rotation is not None:
            self.rotation = rotation
        if rotationQuaternion is not None:
            self.rotationQuaternion = rotationQuaternion
        self.scaling = instancedMesh.scaling
        self.freezeWorldMatrix = instancedMesh.freezeWorldMatrix
        
        if hasattr(instancedMesh, 'physicsImpostor'):
            self.physicsImpostor = instancedMesh.physicsImpostor
            self.physicsMass = instancedMesh.physicsMass
            self.physicsFriction = instancedMesh.physicsFriction
            self.physicsRestitution = instancedMesh.physicsRestitution
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     def to_scene_file(self, file_handler):
        file_handler.write('{')
        write_string(file_handler, 'name', self.name, True)
        if hasattr(self, 'parentId'): write_string(file_handler, 'parentId', self.parentId)
        write_vector(file_handler, 'position', self.position)
        if hasattr(self, 'rotation'):
            write_vector(file_handler, 'rotation', self.rotation)
        else:
            write_quaternion(file_handler, 'rotationQuaternion', self.rotationQuaternion)

        write_vector(file_handler, 'scaling', self.scaling)
        # freeze World Matrix currently ignored for instances
        write_bool(file_handler, 'freezeWorldMatrix', self.freezeWorldMatrix)

        if hasattr(self, 'physicsImpostor'):
            write_int(file_handler, 'physicsImpostor', self.physicsImpostor)
            write_float(file_handler, 'physicsMass', self.physicsMass)
            write_float(file_handler, 'physicsFriction', self.physicsFriction)
            write_float(file_handler, 'physicsRestitution', self.physicsRestitution)
            
file_handler.write('}')

 

Share this post


Link to post
Share on other sites

@JCPalmer thanks for the answer. Can you please check my playground demo? Nothing to edit, just open and check the console - it shows, that mesh "Cube" has no tags, but an instance "Cube.001" does have. I attach a .blend file here - you can see, that both meshes should have the same tag, what doesn't happen in a playground. In an application - If I know, that mesh "Cube" must have a tag - I can't access it, sorry. A bug?

 

Oh, and I have found what causes disabled collisions for all instances except one - when my Blender object is made from different joined meshes with different materials. Example - https://playground.babylonjs.com/#NKZ8CX#1 - one mesh has no more collisions, but the second does have. As you can see, cubes now contain 2 materials. Is that true that we can create instances for meshes with one material only or this is a bug? It looks strange, for example, if you have 1 complex object -> you create 9 instances and suddenly a "parent" becomes one of instances, with collisions enabled, while all other 9 stays without.

 

Do you want me to test anything else to help to solve these issues?

instance.blend

Share this post


Link to post
Share on other sites

Did not look at your blend.  Looking at the long string I see:

"meshes":[{"name":"Cube.001"

Then at the very end of the section  for that mesh there is:

"instances":[{"name":"Cube"

Your assumptions that "Cube.001" is the instance & the mesh is "Cube" is wrong.  Why they both do not have the tag, I do not know.  That is not my PR to read tags in a .babylon.  I also did not add tags to the export, but looks like it works.  If the export is confusing the mesh with the instance, I would look into that, but I am doing my own work right now.  I think the export code defines the mesh as the first one encountered.  In that case, probably not much can be done.  If you refer to them by name, it should not matter (assuming they all get the same tags @Deltakosh)

I have no idea whether the material shared by an instance can in fact be a multi-material.  I am generating a properly formatted .babylon file, as far as I can tell.  If that is not supported, maybe an exception should be thrown.  How this impacts collision, who knows.

Share this post


Link to post
Share on other sites

No worries :) I understand, that you are not the only one who worked on these features. You are just the only one who responded yet, thanks for that, I don't know whom to ask.

2 hours ago, JCPalmer said:

If the export is confusing the mesh with the instance, I would look into that

I think that's the case. Historically "Cube" was created first, then with Alt+D an instance "Cube.001" was created. In .babylon file it is vice-versa.

 

So the questions we have:

1. How to get tags from every instance? Demo shows they are missing.

2. Can we create instances for objects with multiple materials? Demo shows we can, but without collisions.

3. How to enable collisions for instances with multiple materials inside?

 

Let's wait for more experts :)

Share this post


Link to post
Share on other sites

1. Tags are not duplicated when an instance is created but you can just manually call  Tags.AddTagsTo(instance,  source.tags)

2. Instances must have exactly the same material as source. This is the only constraints. Collisions are not related to materials

3. Can you repro only this one? This should not be related at all

Share this post


Link to post
Share on other sites

@Deltakosh, for 1, I did have a link in my first response, where in ParseMesh this exact code is.

On 2,  This is user error.  The tag for instance from his PG contains no physics imposter tags:

"instances":[{"name":"Cube","position":[-2,0,0],"rotation":[0,0,0],"scaling":[1,1,1],"freezeWorldMatrix":false}]}

I also indicated in my first response, the need to add an imposter for each instance in the .blend.  In theory, the data of the object designated by the exporter as the 'Mesh' could also be written for those designated as instances, but I am not. 

I do not think there is some designation in Blender of the "master" mesh & the linked copies other than naming (too weak).  This also might limit when no imposter is wanted.

Share this post


Link to post
Share on other sites

@Deltakosh, I know this is strange, but really - if I join in Blender meshes with the same 1 material and then create an instance - everything is Ok and all collisions exist; but if I join meshes which have different materials and then create an instances - collisions disappear.

PG - https://playground.babylonjs.com/#NKZ8CX#1.

Both objects have exactly the same materials. Left object has become "transparent" and right one still has collisions. I didn't change anything else except materials before creating an instance.

 

@JCPalmer, I do not use additional physics plugins, only built-in "Check Collisions" in Blender.

Share this post


Link to post
Share on other sites

@Deltakosh, great :)

What about tags? As I understood you agreed, that every instance should have the same tags automatically. Simple use case: in Blender you create a house "myHouse", assign a tag "empty" to it, then create some instances to place them somewhere else. They will get names "myHouse.001", "myHouse.002".

But, later if you try to read tag in BJS from your initial house "myHouse" - you will notice that it has disappeared, moreover - it is no longer a parent mesh, but an instance. Now parent mesh is "myHouse.002" somehow and it really contains your tag. Somehow they swap places. My guess is that the latest created instance becomes a parent mesh.

The same PG shows the idea: https://playground.babylonjs.com/#NKZ8CX#1 - console shows that "Cube" has no tags and is not a mesh, however it was created first and tag was assigned to it.

Share this post


Link to post
Share on other sites

Cube.001 is the mesh and Cube is the instance from BJS loading point of view.

So perhaps some inversion happened in the exporter?

I agree on the fact that isntances can have tags and these tags are loaded from the file. But I do not agree  on the fact that instances should have the same as the source mesh. They could be different. It is on you to set the same tags to both objects in Blender

 

Share this post


Link to post
Share on other sites

@Deltakosh, different tags possible for instances is even much more better.

About inversion - yes, some kind of it happens. If I create, for example, 20 instances - then "Cube.020" will become a mesh. I even tried to delete it - then "Cube.019" becomes a mesh :)

 

Can you help with disappearing tags and roles inversion too? Blender shows the same tags automatically for the mesh and all the instances, it may be one of issue reasons too.

Share this post


Link to post
Share on other sites

I do not see a mesh - instance like relationship in the Blender API.  Just meshes which share the same geometry.  The first mesh encountered by the exporter which has shared geometry, gets to be the mesh in BJS.  The simplest way is just to

  • add all your Blender duplicates
  • export once, and look in the log file to see which mesh is the BJS Mesh.
  • Edit THAT meshes tags.

Share this post


Link to post
Share on other sites

@JCPalmer, Kind of solution for a parent mesh, yes. A workaround :) but how to set different tags for different instances? Currently Blender shows the same tags everywhere. If I change the instance's tags - mesh's are changed too.

And one more idea about roles inversion:

2 hours ago, JCPalmer said:

The first mesh encountered by the exporter which has shared geometry, gets to be the mesh in BJS

.. what will happen if you take the last mesh, not the first? Maybe in that case an initial mesh "Cube" will always stay a parent mesh?

Share this post


Link to post
Share on other sites

The order of iterating through the array of meshes would have to be reversed.  Not sure it would always work, since I do not know what drives the order in the first place.  Have no plan to do that when you could just change the name for the mesh that is earliest in the array to be whatever name you wish.

As far as unique tags for each instance (whether the loader reads it or not), I added it to a list. Would not look for it anytime soon.  There is only one other thing on the list & I have my own work.  PR the change yourself, if you wish.

Share this post


Link to post
Share on other sites

@alexoy, checking in Blender, duplicates share a data directory.  The exporter custom properties are in the data directory, as shown on the data tab, so there may only be a single version.  Blender's sharing of data precludes unique tags, so there will be no exporter changes for this.  The "2" in the picture, shows 2 meshes sharing the same data, just like materials and everything else in Blender:

tags2.jpg.2cf1def0e7b9f37c0d766ed189fda844.jpg

I would recommend to use your mesh name to hold your tags.  Something like the format of 'mymesh:tag1,tag2'.  Then have a loop to transfer:
 

for (var i = 0, len = scene.meshes.length; i < len; i++){
    var name = scene.meshes[i].name;
     if (name.startsWith('myMesh:')) {
          scene.meshes[i].tags = name.substr(7);
     }
}

 

Share this post


Link to post
Share on other sites

@JCPalmer, thanks for explanation. So we could think that Blender's mesh is a data container and an instance is more like a reference to this data. Correct?

So the issue with collisions is/will be solved by Deltakosh, tags are common for all Blender instances.

 

The only problem left is about disappearing tags. While all instances should share the same tag - it is not accessible from BJS code. Had you a chance to find what causes this?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.