Jump to content

RBD Magnets with custom VEX forces


juangoretex

Recommended Posts

Hey guys,

I'm trying to make an animation where two magnets float in "space" towards each other, as they get closer they should be attracted to each other with the correct "magnet pole".
I guess that I could animate this with keyframes too, but I thought that simulating it could create some cool, natural movements and happy accidents perhaps.

I'm using RBDs for this and I'm using a POP Wrangle to create the forces, I'm also planning to use a glue constraint for example to get them to stick. But I can't really get them to attract correctly the way I want, they don't seem to both attract towards the correct pole.

I'd much appreciate it if anyone could take a look and give me a few tips!

magnet_snap.hiplc

Link to comment
Share on other sites

@juangoretex
try this 
 

int pB = 1 - @ptnum;

vector  posA = @P;
vector4 qA   = @orient;
vector  upA  = qrotate(qA, {0,0,1});

vector  posB = point(0, "P", pB);
vector4 qB   = point(0, "orient", pB);
vector  upB  = qrotate(qB, {0,0,1});

vector velA = v@v;
vector velB = point(0, "v", pB);

// Compute direction and distance
vector dir   = posB - posA;
float  dist  = length(dir);
dir          = normalize(dir);

// Magnet properties
float maxRange    = chf("maxrange");  // Maximum attraction range
float strength    = chf("strength");  // Force multiplier
float alignThresh = chf("alignment"); // Minimum alignment threshold
float dragFactor  = chf("drag_factor"); // Controls how smoothly objects approach each other

// Retrieve magnet polarity using point()
int polarityA = i@magnet_polarity;
int polarityB = point(0, "magnet_polarity", pB);
int polarityEffect = (polarityA == polarityB) ? -1 : 1; // Same polarity repels, opposite attracts

// Compute force if within range
if (dist < maxRange)
{
    float forceMag = strength * (1.0 - pow(dist / maxRange, 2.0)); // Exponential falloff

    // Check alignment for magnetic influence
    float alignment = dot(upA, dir);
    if (alignment > alignThresh)
    {
        // Attraction/Repulsion force
        vector F = polarityEffect * forceMag * dir;

        // Apply force bidirectionally
        v@force += F;
        setpointattrib(0, "force", pB, -F, "add");

        // Apply drag-based velocity correction for smooth movement
        vector velocityDiff = (posB - posA) * dragFactor;
        v@v += velocityDiff;
        setpointattrib(0, "v", pB, -velocityDiff, "add");

        // Add torque effect to simulate realignment
        vector torqueA = cross(upA, dir) * forceMag * 0.5;
        vector torqueB = cross(upB, -dir) * forceMag * 0.5;

        v@torque += torqueA;
        setpointattrib(0, "torque", pB, torqueB, "add");
    }
}

// Debugging
f@dist_debug = dist;
v@dir_debug = dir;


_____________________________-- second Test......................
// Get opposite magnet's point index
int pB = 1 - @ptnum; 

// Get positions, orientations, and velocities
vector  posA  = @P;
vector4 qA    = @orient;
vector  upA   = qrotate(qA, {0,0,1});
vector  velA  = v@v;

vector  posB  = point(0, "P", pB);
vector4 qB    = point(0, "orient", pB);
vector  upB   = qrotate(qB, {0,0,1});
vector  velB  = point(0, "v", pB);

// Compute direction and distance
vector dir   = posB - posA;
float  dist  = length(dir);
dir          = normalize(dir);

// Magnet properties
float maxRange     = chf("maxrange");  // Maximum range for attraction/repulsion
float strength     = chf("strength");  // Magnet force multiplier
float dragFactor   = chf("drag_factor");  // How smoothly magnets move
float alignmentThreshold = chf("alignment"); // Alignment threshold

// Retrieve magnet polarity
int polarityA = i@magnet_polarity;
int polarityB = point(0, "magnet_polarity", pB);

// Determine attraction or repulsion
int polarityEffect = (polarityA == polarityB) ? -1 : 1;  // Opposite attracts, same repels

// Apply magnetic interaction if within range
if (dist < maxRange)
{
    // Magnetic force calculation with smooth falloff
    float forceMag = strength * (1.0 - pow(dist / maxRange, 2.0)); 

    // Compute alignment
    float alignment = dot(upA, dir);
    if (alignment > alignmentThreshold)
    {
        // Apply force in the direction of the magnetic attraction/repulsion
        vector F = polarityEffect * forceMag * dir;
        
        // Apply forces bidirectionally
        v@force += F;
        setpointattrib(0, "force", pB, -F, "add");

        // Smooth velocity attraction
        vector velocityAdjustment = dir * (forceMag * dragFactor);
        v@v += velocityAdjustment;
        setpointattrib(0, "v", pB, -velocityAdjustment, "add");

        // Add torque to align the magnets
        vector torqueA = cross(upA, dir) * forceMag * 0.5;
        vector torqueB = cross(upB, -dir) * forceMag * 0.5;

        v@torque += torqueA;
        setpointattrib(0, "torque", pB, torqueB, "add");
    }
}

// Debug attributes
f@dist_debug = dist;
v@dir_debug = dir;

 

zvv.gif

zvv01.gif

Edited by Librarian
  • Like 1
Link to comment
Share on other sites

8 hours ago, Librarian said:

@juangoretex
try this 
 

int pB = 1 - @ptnum;

vector  posA = @P;
vector4 qA   = @orient;
vector  upA  = qrotate(qA, {0,0,1});

vector  posB = point(0, "P", pB);
vector4 qB   = point(0, "orient", pB);
vector  upB  = qrotate(qB, {0,0,1});

vector velA = v@v;
vector velB = point(0, "v", pB);

// Compute direction and distance
vector dir   = posB - posA;
float  dist  = length(dir);
dir          = normalize(dir);

// Magnet properties
float maxRange    = chf("maxrange");  // Maximum attraction range
float strength    = chf("strength");  // Force multiplier
float alignThresh = chf("alignment"); // Minimum alignment threshold
float dragFactor  = chf("drag_factor"); // Controls how smoothly objects approach each other

// Retrieve magnet polarity using point()
int polarityA = i@magnet_polarity;
int polarityB = point(0, "magnet_polarity", pB);
int polarityEffect = (polarityA == polarityB) ? -1 : 1; // Same polarity repels, opposite attracts

// Compute force if within range
if (dist < maxRange)
{
    float forceMag = strength * (1.0 - pow(dist / maxRange, 2.0)); // Exponential falloff

    // Check alignment for magnetic influence
    float alignment = dot(upA, dir);
    if (alignment > alignThresh)
    {
        // Attraction/Repulsion force
        vector F = polarityEffect * forceMag * dir;

        // Apply force bidirectionally
        v@force += F;
        setpointattrib(0, "force", pB, -F, "add");

        // Apply drag-based velocity correction for smooth movement
        vector velocityDiff = (posB - posA) * dragFactor;
        v@v += velocityDiff;
        setpointattrib(0, "v", pB, -velocityDiff, "add");

        // Add torque effect to simulate realignment
        vector torqueA = cross(upA, dir) * forceMag * 0.5;
        vector torqueB = cross(upB, -dir) * forceMag * 0.5;

        v@torque += torqueA;
        setpointattrib(0, "torque", pB, torqueB, "add");
    }
}

// Debugging
f@dist_debug = dist;
v@dir_debug = dir;


_____________________________-- second Test......................
// Get opposite magnet's point index
int pB = 1 - @ptnum; 

// Get positions, orientations, and velocities
vector  posA  = @P;
vector4 qA    = @orient;
vector  upA   = qrotate(qA, {0,0,1});
vector  velA  = v@v;

vector  posB  = point(0, "P", pB);
vector4 qB    = point(0, "orient", pB);
vector  upB   = qrotate(qB, {0,0,1});
vector  velB  = point(0, "v", pB);

// Compute direction and distance
vector dir   = posB - posA;
float  dist  = length(dir);
dir          = normalize(dir);

// Magnet properties
float maxRange     = chf("maxrange");  // Maximum range for attraction/repulsion
float strength     = chf("strength");  // Magnet force multiplier
float dragFactor   = chf("drag_factor");  // How smoothly magnets move
float alignmentThreshold = chf("alignment"); // Alignment threshold

// Retrieve magnet polarity
int polarityA = i@magnet_polarity;
int polarityB = point(0, "magnet_polarity", pB);

// Determine attraction or repulsion
int polarityEffect = (polarityA == polarityB) ? -1 : 1;  // Opposite attracts, same repels

// Apply magnetic interaction if within range
if (dist < maxRange)
{
    // Magnetic force calculation with smooth falloff
    float forceMag = strength * (1.0 - pow(dist / maxRange, 2.0)); 

    // Compute alignment
    float alignment = dot(upA, dir);
    if (alignment > alignmentThreshold)
    {
        // Apply force in the direction of the magnetic attraction/repulsion
        vector F = polarityEffect * forceMag * dir;
        
        // Apply forces bidirectionally
        v@force += F;
        setpointattrib(0, "force", pB, -F, "add");

        // Smooth velocity attraction
        vector velocityAdjustment = dir * (forceMag * dragFactor);
        v@v += velocityAdjustment;
        setpointattrib(0, "v", pB, -velocityAdjustment, "add");

        // Add torque to align the magnets
        vector torqueA = cross(upA, dir) * forceMag * 0.5;
        vector torqueB = cross(upB, -dir) * forceMag * 0.5;

        v@torque += torqueA;
        setpointattrib(0, "torque", pB, torqueB, "add");
    }
}

// Debug attributes
f@dist_debug = dist;
v@dir_debug = dir;

 

zvv.gif

zvv01.gif

Hey thank you so much! Helps a lot. Adding the v@torque for alignment between them was a nice touch!

It's still super duper difficult to work with and unstable though, I'm obviously new to RBDs, VEX and Houdini in general so it's tough. I also have no idea how to add glue constraints dynamically during the sim, can't even find any info about it when searching, makes sense that RBD constraints are used for keeping things together before breaking instead of the other way around.

I might just try to animate this. Getting a lot of good reference from playing with this though. Thanks again for taking your time to look into this, appreciated.

Link to comment
Share on other sites

23 hours ago, vicvvsh said:

Hi,

actually there are some information on this forum about rbd constraints:

This is one attempt to achieve magnet force effect in dop. Hip file in attachment.

magnet_force.gif

magnet_snap_01.hipnc 914.23 kB · 5 downloads

Amazing!! Thank you so so much Victor, you did it! This is so valuable, I'll have a thorough look through your file and the links.

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.

×
×
  • Create New...