Hair clipping simulation. needs to detect hair trigger enter and delete hair

I am trying to create hair cutting simulation. I have added a trigger volume in the clipper mesh and each hair has mesh collision added. I want to detect each hair trigger enter with the clipper mesh and delete the hair, instead of trying to add script to each hair and detect collision. hope that makes sense.
So the code below describes best_

var Clipper = pc.createScript('clipper');

// initialize code called once per entity
Clipper.prototype.initialize = function() {
    this.entity.collision.on('triggerenter', () =>{
        //want to destroy the hair not the clipper this.entity.destroy() will destroy the clipper.
    });
};

Your insight will really help.

thanks in advance

So, you want to destroy some entity on collision? You could do it the way you are doing now, just instead of this.entity.destroy() you would call someOtherEntity.destroy(). You just need to define what is someOtherEntity beforehand.

1 Like

Hi, thank you so much for your reply. Problem with defining the someOtherEntity beforehand is that there are many hair strands on the head. not sure how to define each of them beforehand. I want the ‘triggerenter’ event to detect which rigid body entered the trigger volume which is attached to the clipper and delete the hair that triggered the event.

the image shows a simple sinario… where the yellow rectangle shaped box is the clipper and the hair is on the right… the box has the script… and I am hoping to delete hair(s) without adding script to each hair. once the hair enters the trigger volume I want to destroy it from the collision event that the trigger volume with the clipper receives.

Hi @Fire_Picaso,

You can set each hair entity to be a kinematic body (add a rigid body component and set it to kinematic). From the API docs:

When an entity with a dynamic or kinematic body enters or leaves an entity with a trigger volume, both entities will receive trigger events.

Then when they enter the trigger, the triggerenter event will fire and you can get a reference and destroy them like this:

this.entity.collision.on('triggerenter', (otherEntity) =>{
   otherEntity.destroy();    
});
3 Likes

Thank you so much!!! that actually worked.

1 Like

Hi @Leonidas,
Thank you so much for your help. I was trying to import hair and there are lots of them. Is there a way to programmatically attach each hair a mesh collision component and a kinematic rigid body?

during the import, all the hair together is one compound object but each hair is a separate entity.
the image here shows the best

You must use a script then. If you import your model with a hierarchy import option enabled (in project settings asset tasks), then you can search your root entity and collect all your hair entities with a find method. Then add rigidbody and collision components to them.

const hairs = entity.find(function(node) {  
   if (node.name === do_regexp_test) return true;
   return false;
});
for (const hair of hairs) {
  hair.addComponent('rigidbody', { ... });
  hair.addComponent('collision', { ... });
}
3 Likes

If you’d like this to happen in editor, you can use the editor API to automate that work. Multiselect all of your hair entities in editor, open the browser console and run the following code.

It will automatically add a mesh collision and kinematic rigid body components:

editor.selection.items.forEach(o => {
    const renderAssetID = o.get('components.render.asset');

    if(!renderAssetID) return true;

    o.addComponent('collision', {
        type: 'mesh',
        renderAsset: renderAssetID
    });

    o.addComponent('rigidbody', {
        type: 'kinematic'
    });
});
2 Likes

Thank you @LeXXik . I will try it out

Thank you @Leonidas, I will try this out for sure.

Hi @Leonidas, Hi @LeXXik

I need some help on using the event listener functionality. I am triggering an event from the clipper called “UI:hairCutArray” and listening from the game.js script which is the core script in the root. I would like to pass this.userCut array from the clipper object to the game object and do some array comparison with the standard haircut array in the game.js where this.mohawk is an array.

how do I get access to this userCut argument passed by the clipper in the game object.

var Clipper = pc.createScript('clipper');

// initialize code called once per entity
Clipper.prototype.initialize = function(){
    this.userCut = [];
    this.app.on("ui:hairCutDone", this.hairCutDone, this);

    this.entity.collision.on('triggerenter', (other) => {
        this.userCut.push(other.name);
        other.destroy();
    });
    
};

Clipper.prototype.hairCutDone = function(){
    this.app.fire('ui:hairCutArray', this.userCut);
};

This event listener script in the Game object has the following codes.

Game.prototype.initialize = function() {
    this.score = 0;
    
    //Standard haircuts
    this.mohawk = ['LowerNape2_Right_Collision', 'UpperNape2_Right_Collision', 'OccipitalBone1_right_Collision', 'UpperNape3_Right_Collision', 'Side_Right_Collision', 'Temple_Right_Collision', 'ParietalRidge1_right_Collision', 'ParietalRidge3_right_Collision', 'ParietalRidge2_right_Collision', 'ParietalRidge4_Right_Collision', 'LowerNape2_left_Collision', 'UpperNape2_Left_Collision', 'OccipitalBone1_left_collision', 'ParietalRidge4_left_Collision', 'LowerNape3_left_Collision', 'UpperNape3_left_collision', 'Side_Left_Collision', 'ParietalRidge2_Left_Collision', 'Temple_left_collision', 'ParietalRidge1_Left_collision', 'ParietalRidge3_left_Collision'];
    
    // listen to events from the UI
    //Scoring comparison
    this.app.on("ui:hairCutArray", function (){
        for (let i = 0; i < userCut.length; i++){
            if (mohawk.includes(userCut[i])){
                this.score += 1;
            }
        }
        this.score -= Math.abs(this.mohawk.length - userCut.length);
        console.log(this.score);
    }, this);
};

Hi @Fire_Picaso,

Any argument you pass to the event, after the event’s name, when firing it, are available as arguments in the event listener:

this.app.on("ui:hairCutArray", function (userCut){
2 Likes

Thank you so much @Leonidas. You are a life savior!

1 Like