juangoretex Posted Thursday at 04:58 PM Share Posted Thursday at 04:58 PM 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 Quote Link to comment Share on other sites More sharing options...
Librarian Posted Friday at 08:40 AM Share Posted Friday at 08:40 AM (edited) @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; Edited Friday at 09:03 AM by Librarian 1 Quote Link to comment Share on other sites More sharing options...
juangoretex Posted Friday at 05:15 PM Author Share Posted Friday at 05:15 PM 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; 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. Quote Link to comment Share on other sites More sharing options...
vicvvsh Posted Saturday at 11:56 AM Share Posted Saturday at 11:56 AM (edited) 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_snap_01.hipnc Edited Saturday at 11:59 AM by vicvvsh 2 Quote Link to comment Share on other sites More sharing options...
juangoretex Posted Sunday at 11:40 AM Author Share Posted Sunday at 11:40 AM 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_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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.