Detecting Collision on Impact
Debri Source Node
Debri Source node detects the collision impact on a fractured geometry and creates emission points that will be the source points for a particle simulation, which can be rendered as Debri particles.
This node finds points along the edges of each fractured piece and then keeps track of a nearby point belonging to a different piece. It uses these two points to compare the distance and if this distance is greater than a set thershold distance, debri source node will consider that this fractured piece currently in collision.
Finding Nearby Point
In the attribute wrangle named, “find_closest_from_other_piece” the following code is applied to every single point within our fractured geometry.
int handle = pcopen(file, "P", pcP, radius, maxpoints, "preload", 1);
This line will return a group of points that are all within radius distance of our main point in focus, which I will refer to “point A”. That’s the second parameter in the pcopen() function, “P”, which grabs the P position attribute from “point A”. We’ll call this “near group”.
while(pciterate(handle))
{
//Finds the point that is closest
}
Then the while loop goes through each and every point in “near group” and figures out which point is the closest.
string cur_name;
pcimport(handle, "name", cur_name);
if(s@name != cur_name)
{
//Stores the id of the closest point
}
The closest point is found by first eliminating points that have a common piece name. If a point belongs to a piece, for example “piece0”, then that point will have a string attribute named “piece0”. We will only consider the point in “near group” that do not have a common piece name, which means that the points in “near group” cannot belong to the same piece as our point. If they have different names like “piece1” and “piece0”, they are different pieces!
if(i@other_id == @ptnum || dist < other_dist)
{
i@other_id = cur_id;
other_dist = dist;
}
Next we eliminate the point with the same point number as “point A”, because pcopen() function can return the same point and that wouldn’t be very useful to us. We also check the distance to see if any other points within “near group” are closer. It’s like shopping for the better deal or in this case looking for an even closer point.
Our new closest point gets stored in i@other_id.
Impacted Points
Inside the SOP solver, there is an attribute wrangle that figures out if the i@other_id point is far enough to be considered as a collision.
On collision impact, the fractured pieces break apart and after the collision the growing distance between the points and the pieces will be the trigger point for the point to be considered as collision on impact. When the collision impact is detected, our “point A” will now have an attribute i@released = 1, signifying that the point is being broken off.
vector d = point(0, "P", i@other_id);
d -= v@P;
This is grabbing the position of the other_id point (our closest neighboor that we found earlier). Then v@P is our “point A” position.
d is the distance between these two points.
-=
symbol means that
d = d - v@P
So these two lines means:
d = (position of closest neighboor) - (position of point A)
Now moving onto the next line:
float dist = ch("radius");
if(length2(d) > dist * dist)
i@released = 1;
If d distance is big enough, bigger than dist * dist, which is a threshold we get to define in the channel radius, then our point is considered to be on impact and we set the released attribute with a value of 1.
Only Impact Points Remain
In the last attribute wrangle node, if the point isn’t released yet meaning:
i@released = 0
This marks the point still dormant.
float lifespan = ch("../lifespan");
if(i@released == 0 || @age > lifespan)
removepoint(geoself(), @ptnum);
Then we don’t want to see this point yet, therefore we remove the point. Remember we only want the points on impact to show up everything else must be removed.
If our “point A” has been on impact and out lived its lifespan, we’ll remove it as well. We don’t want our impact points to exist for too long. The collision impact only exists for a short time.
float lifespan = ch("../lifespan");
The lifespan is a value we get to set.