Burning in iMSTK-Unity

Like always, I’m still trying to add more of the iMSTK features to Unity, and now is the “Burning” turn. I have done this for the moment, and I have been printing variables and everything seems like it’s OK. Still not working, but I don’t know what can I do to fix it.

using System;
using System.Collections;
using System.Collections.Generic;
using Imstk;
using UnityEngine;

namespace ImstkUnity
{
    public class Burnable : MonoBehaviour
    {
        public DynamicalModel rigidModel;
        Imstk.PbdObject burnableObject;

        Imstk.Burnable burnable;
        Imstk.Burner burner;

        private bool lastEstado = false;
        
        void Start()
        {
            burnableObject = FindPbdObject();
            
            if (rigidModel == null || burnableObject == null)
            {
                Debug.LogWarning("Both models need to be assigned for the Burning Interaction to work");
                enabled = false;
                return;
            }

            if (!rigidModel.isActiveAndEnabled)
            {
                return;
            }
            
            burnable = new Imstk.Burnable(name);
            
            if (burnableObject != null)
                burnableObject.addComponent(Imstk.Utils.CastTo<Imstk.Component>(burnable));
            
            burner = new Imstk.Burner();
            //burner.setWattage(199);
           
            
            PbdObject pbdTool = Imstk.Utils.CastTo<Imstk.PbdObject>(rigidModel.GetDynamicObject());
            if (pbdTool != null) 
                pbdTool.addComponent(Imstk.Utils.CastTo<Imstk.Component>(burner));
            
            burner.addObject(burnableObject);
            
            burner.init();
        }

        private void Update()
        {
            if(Input.GetKeyDown(KeyCode.B))
                startBurning();
            
            if(Input.GetKeyUp(KeyCode.B))
                //burner.stop();
            
            if(burner.getState() != lastEstado)
                print("Estado " + burner.getState());

            lastEstado = burner.getState();
        }

        private void startBurning()
        {
            burner.start();
            print("Watts " + burner.getWattage());
            print("onTime " + burner.getOnTime());
        }
        private Imstk.PbdObject FindPbdObject()
        {
            {
                var deformable = GetComponent<DynamicalModel>();
                if (deformable != null)
                {
                    deformable.dynamicGeometry = true;
                    deformable.ImstkInit();
                    var dynamicalModel = deformable.GetDynamicObject();
                    var pbdObject = Imstk.Utils.CastTo<Imstk.PbdObject>(dynamicalModel);
                    return pbdObject;
                }
                else
                {
                    print("DynamicalModel is null");
                }
                return null;
            }
        }
        
    }
}

your code in Start() should probably be in OnImstkInit() for consistency. There have been some bugs with second ImstkInit() call overwriting an object that already existed i.e. you’re calling it here the first time it creates the internal imstk object. If there is a bug in the Init() function a second call to it might overwrite this and if that is the object that is added to the scene then the burnable component that you added won’t be in the imstk scene. Checking in the C++ debugger if that is in the scene is a good first test

I don’t have the build that I used to install iMSTK-Unity in this computer right now, but I will take a look. For the moment still not working but I think is better than before:

using System;
using System.Collections;
using System.Collections.Generic;
using Imstk;
using UnityEngine;

namespace ImstkUnity
{
    public class Burnable : ImstkBehaviour
    {
        public DynamicalModel rigidModel;
        
        Imstk.PbdObject burnableObject;
        Imstk.Burnable burnable;
        Imstk.Burner burner;
        private bool lastEstado = false;
        
        protected override void OnImstkInit()
        {
            burnableObject = FindPbdObject();
            burner = new Imstk.Burner();
            burnable = new Imstk.Burnable();
            if (rigidModel == null || burnableObject == null)
            {
                Debug.LogWarning("Both models need to be assigned for the Burning Interaction to work");
                enabled = false;
                return;
            }

            if (!rigidModel.isActiveAndEnabled)
            {
                return;
            }
            
            if (burnableObject != null)
                burnableObject.addComponent(Imstk.Utils.CastTo<Imstk.Component>(burnable));
            
            burner.addObject(burnableObject);
            
            PbdObject pbdTool = Imstk.Utils.CastTo<Imstk.PbdObject>(rigidModel.GetDynamicObject());
            if (pbdTool != null) 
                pbdTool.addComponent(Imstk.Utils.CastTo<Imstk.Component>(burner));
        }

        public Imstk.SceneObject GetSceneObject()
        {
            return Imstk.Utils.CastTo<Imstk.SceneObject>(burner);
        }
        private void Update()
        {
            if(Input.GetKeyDown(KeyCode.B))
                startBurning();
            
            if(Input.GetKeyUp(KeyCode.B))
                //burner.stop();
            
            if(burner.getState() != lastEstado)
                print("Estado " + burner.getState());

            lastEstado = burner.getState();
        }

        private void startBurning()
        {
            burner.start();
            print("Watts " + burner.getWattage());
            print("onTime " + burner.getOnTime());
        }
        private Imstk.PbdObject FindPbdObject()
        {
            {
                var deformable = GetComponent<DynamicalModel>();
                if (deformable != null)
                {
                    deformable.dynamicGeometry = true;
                    deformable.ImstkInit();
                    var dynamicalModel = deformable.GetDynamicObject();
                    var pbdObject = Imstk.Utils.CastTo<Imstk.PbdObject>(dynamicalModel);
                    return pbdObject;
                }
                else
                {
                    print("DynamicalModel is null");
                }
                return null;
            }
        }
        
    }
}

EDIT: Good news: Seems like pbdTool is null

burnable onImstkInit() is being executed before rigid, it isn’t null if i try to do it in a coroutine after 0.5f

I did some things on the SimulationManagerEditor to make my custom onImstkInit order and it’s working (pbdtool is not null anymore) but burning is still not working. I’m trying, I’ll say something if I get it.

To be honest, I’m not sure that Burning is working on iMSTK (C++). I just tried to use PbdConnectiveTissueExample who supposedly uses Burnable and Burner, and it’s not doing anything. For example, “g” is used to grasp and “b” to burn, and, in this example, grasping is working for me but burning isn’t. Can you (when you have time) confirm this?

Apart from making the custom execution order to not have null references, my Burning.cs looks like this:

using System;
using System.Collections;
using System.Collections.Generic;
using Imstk;
using UnityEngine;

namespace ImstkUnity
{
    public class Burnable : ImstkBehaviour
    {
        public Rigid rigidModel;
        public DynamicalModel deformableModel;
        
        Imstk.PbdObject burnableObject;
        Imstk.Burnable burnable;
        Imstk.Burner burner;
        private bool lastEstado = false;
        
        protected override void OnImstkInit()
        {
            burnableObject = Imstk.Utils.CastTo<Imstk.PbdObject>(deformableModel.GetDynamicObject());
            burner = new Imstk.Burner();
            burnable = new Imstk.Burnable();
            
            if (rigidModel == null || deformableModel == null)
            {
                Debug.LogWarning("Both models need to be assigned for the Burning Interaction to work");
                enabled = false;
                return;
            }

            if (!rigidModel.isActiveAndEnabled)
            {
                return;
            }
            
            if (!deformableModel.isActiveAndEnabled)
            {
                return;
            }
            
            deformableModel.dynamicGeometry = true;
            deformableModel.isCuttable = true;
            
            if (burnableObject != null)
                burnableObject.addComponent(Imstk.Utils.CastTo<Imstk.Component>(burnable));
            
            burner.addObject(burnableObject);
            burner.setWattage(200);
            burner.setOnTime(0.5f);
            Imstk.PbdObject pbdTool = rigidModel.GetDynamicObject() as PbdObject;
            if (pbdTool != null)
                pbdTool.addComponent(Imstk.Utils.CastTo<Imstk.Component>(burner));
            else
                Debug.Log("Rigid es null!");
        }
        
        private void Update()
        {
            if(Input.GetKeyDown(KeyCode.B))
                startBurning();
            
            if(Input.GetKeyUp(KeyCode.B))
                burner.stop();

            if (burner.getState() != lastEstado)
            {
                print("Estado " + burner.getState());
                print("Quemable " + burnable.getPbdObject().getName());
            }
                

            lastEstado = burner.getState();
        }

        private void startBurning()
        {
            burner.start();
        }

    }
}

Another update: I wrote some debugging lines and now it’s apparently working in C++. I don’t know why but Unity mesh isn’t reacting to it, even using the same code that I use to update the tetrahedral mesh when adding tearing (This should be enough, right?).


image

EDIT: C++ is returning meshes with the same number of triangles before andafter burning, so doesn’t seem like PbdObjectCellRemoval is working (Unless triangle are not variable even after burning them.

I think I can say that iMSTK Burnable::visualUpdate(const double& dt) isn’t being called. I have some logs in there (The same ones that worked for the last message, so is not about build config) and anything is displayed. What I understood is void visualUpdate() override {} // Called per VTKViewer::update is calledby VTKViewer, and this is out of my knowledge. Any clue will be good for helping me to do this

This might be the first component the needs visualUpdate() called on it. So here try
https://gitlab.kitware.com/iMSTK/imstk-unity/-/blob/main-version-2/Scripts/SimulationManager.cs#L314 add _currentScene.updateVisuals() this has to be after the Monitor.Enter() call

YES, WORKING! I have the same problem as always, the UV, but doesn’t matter for now! Thank you again Harald!

I have a simple particle system to simulate smoke in another scene, if I fix the UV problem, it’s gonna be a very cool result!