{"id":1475,"date":"2024-11-13T01:07:43","date_gmt":"2024-11-12T16:07:43","guid":{"rendered":"https:\/\/heyyocg.link\/?p=1475"},"modified":"2024-11-14T10:06:05","modified_gmt":"2024-11-14T01:06:05","slug":"ue4-27-niagara-advanced-position-based-dynamics-rigid-constraint-chain","status":"publish","type":"post","link":"https:\/\/heyyocg.link\/en\/ue4-27-niagara-advanced-position-based-dynamics-rigid-constraint-chain\/","title":{"rendered":"Niagara Advanced Guide &#8211; Chain Simulation with PBD"},"content":{"rendered":"\n<p>Epic Games distributes a project called &#8220;Content Examples,&#8221; which is a collection of various sample projects showcasing different features of Unreal Engine. Since UE4.26, there is a map called <em>Niagara Advanced<\/em>.<\/p>\n\n\n\n<p>This map contains a wealth of useful samples, including examples of new Niagara features and practical applications. Upon reviewing the implementations, there&#8217;s a lot to learn.<\/p>\n\n\n\n<p>This article will break down these samples into multiple parts for detailed explanations.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"621\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-2-1024x621.png\" alt=\"\" class=\"wp-image-1466\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-2-1024x621.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-2-300x182.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-2-768x466.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-2-1536x932.png 1536w, https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-2-2048x1242.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>By the way, <em>Content Examples<\/em> can be downloaded from <a href=\"https:\/\/www.fab.com\/listings\/4d251261-d98c-48e2-baee-8f4e47c67091\">this link<\/a> in Fab. Please note that the content may vary depending on the version of UE.<\/p>\n\n\n\n<p>\u203bNote: This blog is written based on UE4.27 Contents Example, so it might differ from the latest version in small details, but the concept itself explained here won\u2019t change.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">TLDR;)<\/h2>\n\n\n\n<ul>\n<li>You can implement PBD in Niagara and simulate real-time rigid constraints, like a chain simulation.<\/li>\n\n\n\n<li>Since you can combine this with existing Niagara modules, you can easily add forces like gravity or random shaking.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>In this article, we will discuss an advanced application of <a href=\"https:\/\/heyyocg.link\/en\/ue4-26-niagara-advanced-position-based-dynamics-basic\/\" data-type=\"link\" data-id=\"https:\/\/heyyocg.link\/en\/ue4-26-niagara-advanced-position-based-dynamics-basic\/\">the previously introduced Position-Based Dynamics (PBD)<\/a> by explaining a sample of a chain simulation using PBD. This corresponds to the &#8220;2.4 Iterative Constraints&#8221; section in Niagara Advanced.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2.4 Iterative Constraints Explanation<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"600\" height=\"400\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/Chain_SimulationStages-2021-12-06-23-25-23_1.gif\" alt=\"\" class=\"wp-image-564\"\/><\/figure>\n\n\n\n<p>This sample demonstrates how to simulate the movement of a rigid constraint, like a chain, that does not stretch or shrink, using PBD.<\/p>\n\n\n\n<p>In the video above, the chain is swaying back and forth, and each ring in the chain is represented by a Mesh Particle. The topmost particle has a programmed hard-coded movement, while the other particles are influenced by existing force modules and undergo position correction via PBD, ultimately giving the appearance of a connected chain moving.<\/p>\n\n\n\n<p>Let\u2019s take a look at the overall structure.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"630\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232306-1024x630.png\" alt=\"\" class=\"wp-image-566\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232306-1024x630.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232306-300x185.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232306-768x473.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232306-816x502.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232306.png 1472w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The setup consists of a single Emitter. Since we are using the Simulation Stage, it needs to be set to GPU simulation.<\/p>\n\n\n\n<p>In the light green section, various parameters for the simulation are initialized, and initial positions and rotations for the particles are set.<\/p>\n\n\n\n<p>In the light blue section, various forces are applied to the particles using existing modules.<\/p>\n\n\n\n<p>The purple module is used to cancel forces and manually animate the position of the topmost particle.<\/p>\n\n\n\n<p>Finally, in the red section, PBD is implemented. The main logic runs in the Simulation Stage, where the position correction is repeated 48 times per frame.<\/p>\n\n\n\n<p>Let\u2019s break this down in detail.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Chain Initialization<\/h4>\n\n\n\n<p>First, we configure the simulation parameters.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"790\" height=\"357\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232429.png\" alt=\"\" class=\"wp-image-569\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232429.png 790w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232429-300x136.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232429-768x347.png 768w\" sizes=\"(max-width: 790px) 100vw, 790px\" \/><\/figure>\n\n\n\n<ul>\n<li><strong>Chain Origin<\/strong>: The starting point of the chain.<\/li>\n\n\n\n<li><strong>Chain Segment Length<\/strong>: The distance between each ring in the chain (this is adjusted to match the size of the mesh).<\/li>\n\n\n\n<li><strong>Number Of Chain Segments<\/strong>: The number of links in the chain (the number of particles spawned corresponds to this value).<\/li>\n\n\n\n<li><strong>Weight Per Chain Link<\/strong>: The mass of each chain link (in this sample, this value is not used in the simulation).<\/li>\n<\/ul>\n\n\n\n<p>Since PBD needs to know the positions of neighboring particles during the simulation, we also initialize the Particle Attribute Reader.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"479\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232353-1024x479.png\" alt=\"\" class=\"wp-image-570\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232353-1024x479.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232353-300x140.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232353-768x359.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232353-816x382.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-06-232353.png 1268w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The <strong>Configure Chain<\/strong> module is a Scratch Pad Module that simply stores the initialized values in the Emitter\u2019s attributes.<\/p>\n\n\n\n<p>Next, <strong>Spawn Burst Instantaneous<\/strong> spawns the number of particles specified by <strong>Number Of Chain Segments<\/strong> all at once.<\/p>\n\n\n\n<p>The <strong>Initialize Chain Constraint<\/strong> module initializes the positions and parameters of each particle representing the chain links.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"362\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005622-1024x362.png\" alt=\"\" class=\"wp-image-573\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005622-1024x362.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005622-300x106.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005622-768x271.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005622-816x288.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005622.png 1266w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>First, we initialize the positions of the particles. Using the values set in <strong>Configure Chain<\/strong> (starting point, number of particles, distance between particles), the particles are placed step-by-step in the negative Z direction.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"624\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005652-1024x624.png\" alt=\"\" class=\"wp-image-574\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005652-1024x624.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005652-300x183.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005652-768x468.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005652-816x497.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005652.png 1133w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, we assign the following attributes to each particle:<\/p>\n\n\n\n<ul>\n<li><strong>ChainSegmentLength<\/strong>: The initial length between particles (this will become the constraint in PBD).<\/li>\n\n\n\n<li><strong>ChainGoalDistanceFromOrigin<\/strong>: The total length of the chain.<\/li>\n\n\n\n<li><strong>ChainEndPoint<\/strong>: Flag indicating if the particle is at the end of the chain.<\/li>\n\n\n\n<li><strong>ChainStartPoint<\/strong>: Flag indicating if the particle is at the start of the chain.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"462\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005724-1024x462.png\" alt=\"\" class=\"wp-image-575\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005724-1024x462.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005724-300x135.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005724-768x347.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005724-816x368.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005724.png 1050w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>To prevent the start particle from being affected by forces, we create an <strong>InverseMass<\/strong> attribute. We set it to 0 for the start particle and 1 for the others.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"629\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005809-1024x629.png\" alt=\"\" class=\"wp-image-576\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005809-1024x629.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005809-300x184.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005809-768x471.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005809-816x501.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005809.png 1238w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In PBD, each particle adjusts its position based on the distance from its neighboring particles. To facilitate this, we store the IDs of neighboring particles so that they can be referenced later in the Particle Attribute Reader.<\/p>\n\n\n\n<p>Unlike <strong>Execution Index<\/strong>, particle IDs are unique even when new particles are generated, so using IDs is safer, especially when some particles are completely fixed in place.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"491\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005831-1024x491.png\" alt=\"\" class=\"wp-image-577\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005831-1024x491.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005831-300x144.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005831-768x368.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005831-816x391.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005831.png 1187w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The mass value is stored in the <strong>Mass<\/strong> attribute, which will affect calculations when forces are applied in Niagara.<\/p>\n\n\n\n<p>At the end of the chain initialization section, we also initialize the particle rotations. The goal is for the chain to rotate 90 degrees sequentially as it connects. We adjust the rotation based on whether the <strong>Execution Index<\/strong> is even or odd.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"812\" height=\"609\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005936.png\" alt=\"\" class=\"wp-image-578\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005936.png 812w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005936-300x225.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-005936-768x576.png 768w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Force Configuration<\/h4>\n\n\n\n<p>The force part uses existing modules like <strong>Drag<\/strong>, <strong>Gravity Force<\/strong>, <strong>Curl Noise Force<\/strong>, and <strong>Wind Force<\/strong>, so we\u2019ll skip the explanation here.<\/p>\n\n\n\n<p>On the other hand, you can easily add more modules here to create different types of movements.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"400\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/Chain_SimulationStages-2021-12-06-23-26-22_1.gif\" alt=\"\" class=\"wp-image-581\"\/><\/figure>\n\n\n\n<p>By the way, if you deactivate all the force modules, you will get the movement shown in the video above. As mentioned earlier, the start particle is hard-coded to move, and the remaining particles follow it through PBD.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Configuring the Start Particle\u2019s Movement<\/h4>\n\n\n\n<p>The <strong>Update Chain Segments After Forces<\/strong> module cancels the forces applied to the start particle and applies its own movement. This is done using a Scratch Pad Module, so let\u2019s take a look at its contents.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"566\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013453-1024x566.png\" alt=\"\" class=\"wp-image-582\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013453-1024x566.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013453-300x166.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013453-768x425.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013453-816x451.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013453.png 1219w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We multiply <strong>PhysicsForce<\/strong>, <strong>Velocity<\/strong>, and <strong>PhysicsDrag<\/strong> by <strong>InverseMass<\/strong>, so these values are 0 for the start particle.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"581\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013511-1024x581.png\" alt=\"\" class=\"wp-image-583\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013511-1024x581.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013511-300x170.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013511-768x436.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013511-816x463.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-013511.png 1213w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We then set the start particle\u2019s position by adding an offset to <strong>ChainOrigin<\/strong>. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"659\" height=\"406\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-010040.png\" alt=\"\" class=\"wp-image-579\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-010040.png 659w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-010040-300x185.png 300w\" sizes=\"(max-width: 659px) 100vw, 659px\" \/><\/figure>\n\n\n\n<p>The offset moves in a sine curve along the x, y, and z axes over time, which animates the start particle\u2019s movement.<\/p>\n\n\n\n<p>If you disable the start particle\u2019s animation, you\u2019ll get the movement shown in the video below, where the start particle is fixed and the lower part of the chain sways under the influence of forces.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"400\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/Chain_SimulationStages-2021-12-06-23-26-59_1.gif\" alt=\"\" class=\"wp-image-587\"\/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Coloring for Visualization<\/h4>\n\n\n\n<p>In the overview section, I didn\u2019t mention the modules <strong>Find Kinetic and Potential Energy<\/strong> and <strong>Colorize Chain Based on Kinetic Energy (Color Module)<\/strong>. These calculate the kinetic energy of the particles and use that value to color them, with the particles glowing blue based on the energy. This is a simple visualization and doesn\u2019t require further explanation.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">PBD Implementation<\/h4>\n\n\n\n<p>PBD does not calculate an object\u2019s position from its velocity through mechanical equations. Instead, it adjusts the position iteratively to satisfy constraints. This method may lack some precision, but it allows for fast and robust simulations of complex movements, making it a popular choice for real-time applications.<\/p>\n\n\n\n<p>In this example, the constraint is that the distance between particles cannot exceed a maximum value (the <strong>Chain Segment Length<\/strong> of 5.4). In the Particle Update stage, the particle\u2019s position is adjusted to meet this constraint after external forces and velocity are applied.<\/p>\n\n\n\n<p>The adjustment method is simple: calculate the distance to the neighboring particles, and if the distance exceeds the constraint, move the particle in that direction to correct the position.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"589\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-3-1024x589.png\" alt=\"\" class=\"wp-image-1478\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-3-1024x589.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-3-300x172.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-3-768x442.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-3-1536x883.png 1536w, https:\/\/heyyocg.link\/wp-content\/uploads\/2024\/11\/image-3-2048x1177.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>By performing this adjustment repeatedly, the system converges toward the optimal solution. In this example, the adjustment is performed 48 times per frame for each particle.<\/p>\n\n\n\n<p>The more iterations you perform, the higher the accuracy, but naturally, the process will take more time.<\/p>\n\n\n\n<p>Let&#8217;s take a look at the implementation.<br>There are four modules responsible for PBD within the Simulation Stage.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"279\" height=\"123\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230606.png\" alt=\"\" class=\"wp-image-591\"\/><\/figure>\n\n\n\n<p>As shown below, the position adjustment process is repeated 48 times.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"410\" height=\"189\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230640.png\" alt=\"\" class=\"wp-image-592\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230640.png 410w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230640-300x138.png 300w\" sizes=\"(max-width: 410px) 100vw, 410px\" \/><\/figure>\n\n\n\n<p><strong>Solve Chain Constraint<\/strong> performs the position adjustment as described earlier.<br>Let\u2019s take a closer look at the module\u2019s implementation.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"516\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230724-1024x516.png\" alt=\"\" class=\"wp-image-593\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230724-1024x516.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230724-300x151.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230724-768x387.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230724-816x411.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230724.png 1294w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>First, the <strong>Particle Attribute Reader<\/strong> retrieves the positions of the neighboring particles using the stored particle IDs.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"474\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230801-1024x474.png\" alt=\"\" class=\"wp-image-594\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230801-1024x474.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230801-300x139.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230801-768x356.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230801-816x378.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230801.png 1449w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Then, the <strong>Calculate Link Constraint<\/strong> module script is passed the current position, neighboring particle positions, constraint distance, and a flag for pinning (whether the particle is fixed in place). The module outputs an <strong>UpdatedPosition<\/strong> that represents the adjusted position, which is then stored in the <strong>Position Attributes<\/strong>.<\/p>\n\n\n\n<p>The <strong>Pinned<\/strong> flag ensures that the start particle\u2019s position doesn\u2019t change, as it is not affected by position adjustments.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"418\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231425-1024x418.png\" alt=\"\" class=\"wp-image-598\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231425-1024x418.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231425-300x122.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231425-768x313.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231425-1536x627.png 1536w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231425-816x333.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231425.png 1782w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Inside the <strong>Calculate Link Constraint<\/strong> script, the direction vectors between particles are calculated. If the distance exceeds the constraint length, the particles are adjusted by the difference in distance in the direction of the vector.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"485\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231444-1024x485.png\" alt=\"\" class=\"wp-image-599\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231444-1024x485.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231444-300x142.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231444-768x364.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231444-1536x728.png 1536w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231444-816x387.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231444.png 1840w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The calculation for the rear particles is done in the same way, and their vectors are determined.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"534\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231516-1024x534.png\" alt=\"\" class=\"wp-image-600\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231516-1024x534.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231516-300x156.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231516-768x400.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231516-1536x801.png 1536w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231516-816x425.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231516.png 1738w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Then, the two vectors are added together and divided by 2. The resulting value is added to the particle&#8217;s original position, and the adjusted position is output as the <strong>UpdatedPosition<\/strong>. If the <strong>CurrentPinned<\/strong> flag is set to True, the position is not adjusted, and the original position is output instead.<\/p>\n\n\n\n<p>This is how the position adjustment is calculated within the <strong>Calculate Link Constraint<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"440\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230829-1024x440.png\" alt=\"\" class=\"wp-image-595\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230829-1024x440.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230829-300x129.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230829-768x330.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230829-816x351.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230829.png 1473w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, to adjust the chain&#8217;s orientation, the vector to the previous particle is calculated and stored in <strong>ChainLinkDirection<\/strong>, which is then output. Since the end particle does not have a previous particle, the vector to the next particle is used instead.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"654\" height=\"183\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230848.png\" alt=\"\" class=\"wp-image-596\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230848.png 654w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-230848-300x84.png 300w\" sizes=\"(max-width: 654px) 100vw, 654px\" \/><\/figure>\n\n\n\n<p>Then, the <strong>Orient Mesh to Vector<\/strong> module (an existing module) takes the vector to the previous particle and inputs it into the <strong>Look At Direction<\/strong>. This ensures that the chain properly aligns in that direction.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"356\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231026-1024x356.png\" alt=\"\" class=\"wp-image-597\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231026-1024x356.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231026-300x104.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231026-768x267.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231026-1536x534.png 1536w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231026-816x283.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-07-231026.png 1730w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Finally, <strong>Calculate Accurate Velocity<\/strong> recalculates the velocity based on the adjusted position. The calculation is straightforward: subtract the previous frame\u2019s position from the updated position and divide by the delta time.<\/p>\n\n\n\n<p>In PBD, instead of calculating velocity from position, we recalculate the position from velocity to avoid any discrepancies during the next frame\u2019s update.<\/p>\n\n\n\n<p>I briefly skipped over explaining the <strong>Constrain Chain to Max Length<\/strong> Scratch Pad module in the Particle Update stage. This module checks if any particles have moved too far from the chain&#8217;s origin (beyond the total chain length). If they have, the module brings them back within the allowable range before the PBD position adjustment occurs. Although this step is not strictly necessary for this sample, it helps the PBD adjustments converge more efficiently.<\/p>\n\n\n\n<p>The implementation is based on the same <strong>Calculate Link Constraint<\/strong> script, but with slightly different parameters.<\/p>\n\n\n\n<p>That concludes the explanation of &#8220;2.4 Iterative Constraints.&#8221;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>I was personally surprised by how simple the logic is for creating realistic rigid constraint movement with PBD.<\/p>\n\n\n\n<p>As for performance, this sample (32 particles \u00d7 48 iterations) takes about 1ms for the PBD calculations on an RTX 2080. In a game environment, this may vary based on the situation, but for video and similar applications, this should be more than sufficient.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"298\" height=\"125\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c8-2021-12-08-011506.png\" alt=\"\" class=\"wp-image-606\"\/><\/figure>\n\n\n\n<p>For instance, I tested with 100 particles and 60 iterations, and it took about 1\u20133ms. This is a reasonable load, but as always, it&#8217;s good to keep performance in mind.<\/p>\n\n\n\n<p>One of the best things about this setup is that it can be combined with existing modules. It\u2019s great for creating interactive simulations with collisions.<\/p>\n\n\n\n<p>I tried creating a <em>Mario Goomba<\/em> character as an experiment, which I share in a separate article!<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"twitter-tweet\" data-width=\"500\" data-dnt=\"true\"><p lang=\"ja\" dir=\"ltr\">WanWan in Mario!<br>The movement of the chain is simulated in realtime in Niagara by PDB method.<br>UE\u306e\u30a2\u30c9\u30d9\u30f3\u30c8\u30ab\u30ec\u30f3\u30c0\u30fc\u3067\u89e3\u8aac\u8a18\u4e8b\u66f8\u304d\u307e\u3059<a href=\"https:\/\/twitter.com\/hashtag\/UE4?src=hash&amp;ref_src=twsrc%5Etfw\">#UE4<\/a> <a href=\"https:\/\/twitter.com\/hashtag\/Niagara?src=hash&amp;ref_src=twsrc%5Etfw\">#Niagara<\/a> <a href=\"https:\/\/t.co\/8AhQJkw66T\">pic.twitter.com\/8AhQJkw66T<\/a><\/p>&mdash; HeyYo (@yo_hanashima) <a href=\"https:\/\/twitter.com\/yo_hanashima\/status\/1467857097715232768?ref_src=twsrc%5Etfw\">December 6, 2021<\/a><\/blockquote><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<\/div><\/figure>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-heyyo-cg wp-block-embed-heyyo-cg\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"bAGd7rVrwp\"><a href=\"https:\/\/heyyocg.link\/en\/niagara-pbd-wanwan\/\">Let&#8217;s Create Mario&#8217;s Chain Chomp in Niagara \u2013 Real-Time Chain Simulation Using the PBD Method<\/a><\/blockquote><iframe class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"&#8220;Let&#8217;s Create Mario&#8217;s Chain Chomp in Niagara \u2013 Real-Time Chain Simulation Using the PBD Method&#8221; &#8212; HeyYo CG\" src=\"https:\/\/heyyocg.link\/en\/niagara-pbd-wanwan\/embed\/#?secret=L4G5MeXEAV#?secret=bAGd7rVrwp\" data-secret=\"bAGd7rVrwp\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>In conclusion, while using PBD for interactive simulations with collision still presents some challenges, I believe it can be incredibly useful in many other cases, and I look forward to seeing more examples of PBD in use.<\/p>\n\n\n\n<p>Happy CG creation!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Epic Games distributes a project called &#8220;Content Examples,&#8221; which is a collection of various sample projects showcasing different features of Unreal Engine. Since UE4.26, there is a map called Niagara Advanced. This map contains a wealth of useful samples, including examples of new Niagara features and practical applications. Upon reviewing the implementations, there&#8217;s a lot [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":605,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"no","_lmt_disable":"","_mi_skip_tracking":false,"footnotes":"","_locale":"en_US","_original_post":"http:\/\/heyyocg.link\/?p=560"},"categories":[17,31],"tags":[32,15,30],"modified_by":"yohanashima","_links":{"self":[{"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/posts\/1475"}],"collection":[{"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/comments?post=1475"}],"version-history":[{"count":2,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/posts\/1475\/revisions"}],"predecessor-version":[{"id":1491,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/posts\/1475\/revisions\/1491"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/media\/605"}],"wp:attachment":[{"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/media?parent=1475"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/categories?post=1475"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/tags?post=1475"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}