|
| 28 Feb 2015 09:17 PM |
Verlet Integration and Constraining Explained on Roblox(My first tutorial on anything :3)
Prerequisites: Algebra and an intermediate understanding of lua(Tables and Variable Functions)
_VERLET INTEGRATION_
So you wanna learn Verlet integration? First off we have to understand what Verlet integration is in the first place. Verlet integration is a formula that takes the last position of an object and the current position of an object/point then determines the direction that object/point would continue to travel in, which is basically simulation inertia or “Newton’s First Law”; an object in motion stays in motion.
The bare formula: ------------------------------------- Xn = Xc + (Xp-Xo) + a * Dt^2 ------------------------------------- “Xn”-is the new/calculated position/axis value of the point.
“Xc”-is the current position/axis value of the point.
“Xp”-is the previous position/axis value of the point(previous means 1 frame ago).
“a”-is the velocity that constantly acts on the point, for example gravity(which only should affect the Y-Axis)
“Dt”-is the Delta time, also known as the amount of time between this frame and the last frame. Delta time is used to move the point in small increments every frame.
(Xp-Xo) is the new velocity, the new direction and speed.
Ok, lets now write a simple function to put to use what we’ve just learned :3
------------------------- function Calculate(Part,Prev_Position, DeltaTime) --You can also use a Vector3 value as a point in empty space rather than a part, then apply it to your point(s) afterwards, but you would have to store its individual positions, axis, and etc in a table)
--If you’re using a Vector3 just refer directly to the vector rather than Part.Position) In this example i’ll be using a part since it’s easier to visualize
--We’re going to calculate each axis of the point/part/vector by themselves then combine it in the end to keep things less complicated
local Acc_X = 0 local Acc_Y = Gravity --define your amount of gravity here local Acc_Z = 0 -- Acc is the acceleration/velocity
local Next_X = Part.Position.X + ( Part.Position.X - Prev_Position.X) + Acc_X * DeltaTime^2
local Next_Y = Part.Position.Y + ( Part.Position.Y - Prev_Position.Y) + Acc_Y * DeltaTime^2
local Next_Z = Part.Position.Z + ( Part.Position.Z - Prev_Position.Z) + Acc_Z * DeltaTime^2
Prev_Position.X = Part.Position.X Prev_Position.Y = Part.Position.Y Prev_Position.Z = Part.Position.Z
-- Change the previous Positions to our current one(Notice: I haven’t applied the Next_X/Y/Z yet)
Part.Position = Vector3.new(Next_X ,Next_Y ,Next_Z)
--Now we set the apply the new positions/axis we calculated(Next_X/Y/Z)
end ------------------------- It is ideal that you call this function from a loop, preferably renderstepped, that calculates delta time for you.
_CONSTRAINING_ Constraining is when you have a multiple set of points that you want to keep an equal distance away from each other. This is especially useful for making things such as ropes and cloth(haven’t attempted cloth yet). Then you can draw lines between these points to “render” your rope/cloth. More info on ropes in the end.
Ok, lets , again, write up a simple function to do this. This time I will be referring to a point(a table with axis values) rather than a part. ------------------------- function Constrain(PointA , PointB , Length) local diffX = PointA.Position.X - PointB.Position.X local diffY = PointA.Position.Y - PointB.Position.Y local diffZ = PointA.Position.Z - PointB.Position.Z --Position.X/Y/Z are entries of the table referred to as “PointA”/”PointB”(Omg we made our own imaginary instance!
--Length is the desired distance between each point
local Dist = math.sqrt(diffX^2 + diffY^2 + diffZ^2)
--Dist is the total distance between both points in a 3D enviroment(magnitude) local Difference = (Length - Dist)/Dist
--Difference is how much distance/offset needed before it reaches the desired distance local translateX = diffX * 0.5 * Difference local translateY = diffY * 0.5 * Difference local translateZ = diffZ * 0.5 * Difference --if PointA.Pinned == false then --PointA.Position = Vector3.new( PointA.Position.X - translateX , PointA.Position.Y - translateY , PointA.Position.Z - translateZ) --end
--Updating Point A will cause the points to go insane and fly everywhere so i just leave it commented, i’ll explain pinning later
PointB.Position = Vector3.new( PointB.Position.X - translateX , PointB.Position.Y - translateY , PointB.Position.Z - translateZ) --Again we combine all the axis at the very end
end ------------------------- Pinning is when you don’t apply any changes to a certain point(s), for example the root point of a rope, the point that everything is constrained in “chain” to. The way you should go about about chaining together/constraining ropes is as follows(literally :3):
RootPoint<--Point1<--Point2<--Point3<-- Point4<--So on
You can write a function to position the RootPoint to a part such as your torso so you can have a tail :3
|
|
|
| Report Abuse |
|
|
|
| 28 Feb 2015 09:22 PM |
Hey, nice thread. Haven't read it yet.
We definitely need more threads like this and stravant's explanation of CFrame math. Would be nice to have. |
|
|
| Report Abuse |
|
|
|
| 28 Feb 2015 09:22 PM |
Revision of first paragraph:
So you wanna learn Verlet integration? First off we have to understand what Verlet integration is in the first place. Verlet integration is a formula that takes the last position of an object/point and the current position of the object/point then determines the direction that object/point would continue to travel in, which is basically a simulation of inertia or “Newton’s First Law”; "an object in motion stays in motion". |
|
|
| Report Abuse |
|
|
|
| 28 Feb 2015 09:24 PM |
Revision of the formula:
Xn = Xc + (Xc-Xp) + a * Dt^2 |
|
|
| Report Abuse |
|
|
instawin
|
  |
| Joined: 04 Jun 2013 |
| Total Posts: 8777 |
|
|
| 28 Feb 2015 09:24 PM |
hot
i'll probably have to read this over a couple of times though lel |
|
|
| Report Abuse |
|
|
| |
|
IIIIIIlII
|
  |
| Joined: 06 Jan 2011 |
| Total Posts: 710 |
|
| |
|
|
| 28 Feb 2015 10:21 PM |
| 11/10 You should become a new Roblox wiki editor. |
|
|
| Report Abuse |
|
|
vydlv
|
  |
| Joined: 08 Jun 2010 |
| Total Posts: 1517 |
|
| |
|
|
| 01 Mar 2015 12:32 AM |
| I thought this would be life changing :l |
|
|
| Report Abuse |
|
|
LucasLua
|
  |
| Joined: 18 Jun 2008 |
| Total Posts: 7386 |
|
|
| 01 Mar 2015 12:48 AM |
| Don't worry, I have this thread saved. I'll be using it in the near future, I can assure you. Also now anyone who searches it on google will find it too! |
|
|
| Report Abuse |
|
|
|
| 01 Mar 2015 01:28 AM |
| //Lucas, greatly appreciated :) |
|
|
| Report Abuse |
|
|
|
| 01 Mar 2015 02:32 AM |
i still dont get it a working example would help |
|
|
| Report Abuse |
|
|
MiniNob
|
  |
| Joined: 14 May 2013 |
| Total Posts: 822 |
|
| |
|
IIIIIIlII
|
  |
| Joined: 06 Jan 2011 |
| Total Posts: 710 |
|
|
| 01 Mar 2015 10:09 AM |
smrt math.sqrt(a^2 + b^2 + c^2) |
|
|
| Report Abuse |
|
|
MiniNob
|
  |
| Joined: 14 May 2013 |
| Total Posts: 822 |
|
|
| 01 Mar 2015 11:02 AM |
| How would you make the rope have two pinned points? |
|
|
| Report Abuse |
|
|
|
| 01 Mar 2015 11:09 AM |
| Nice tutorial, might keep this page in my favorites just in case I need some help with ROBLOX physics. |
|
|
| Report Abuse |
|
|
vydlv
|
  |
| Joined: 08 Jun 2010 |
| Total Posts: 1517 |
|
|
| 01 Mar 2015 12:02 PM |
yeah I have this thread tracked, this seems really cool, I just have no clue how to apply it because I'm not that good lol
I mean you did a great job explaining just what it is, it's just I have no idea what I could do with it |
|
|
| Report Abuse |
|
|
MiniNob
|
  |
| Joined: 14 May 2013 |
| Total Posts: 822 |
|
| |
|
|
| 01 Mar 2015 12:32 PM |
If your points are in a table you can manually go through the table and tell which point is pinned.
This is the code I use to generate a set of points:
for i = 1,NumberOfSegments,1 do local NewPoint = { Acc_X = 0, Acc_Y = 0, Acc_Z = 0, Vel_X = 0, Vel_Y = 0, Vel_Z = 0, Next_X = 0, Next_Y = 0, Next_Z = 0, Prev_X = 0, Prev_Y = 0, Prev_Z = 0, Position = Vector3.new(0,10,0), Pinned = false } if i == 1 then NewPoint.Pinned = true -- Making a root, first points will always be pinned NewPoint.Position = Vector3.new(0,30,0) end if i > 1 then NewPoint.Position = Vector3.new((i*2),30 ,0) -- Equal initial spacing between points Prev_X = (i*2) end table.insert(PointStorage,NewPoint) print(NewPoint.Pinned) end |
|
|
| Report Abuse |
|
|
|
| 01 Mar 2015 12:37 PM |
Can I have code to show me how to apply it, I'm really confused + I'm terrible at metatables and just table storage in general
Rolf sweats himself to understand your modern go-go world. |
|
|
| Report Abuse |
|
|
|
| 01 Mar 2015 01:14 PM |
Example, hopefuly you learn something from it:
http://www.roblox.com/Rope-Example-item?id=222174211 |
|
|
| Report Abuse |
|
|
| |
|
MiniNob
|
  |
| Joined: 14 May 2013 |
| Total Posts: 822 |
|
|
| 01 Mar 2015 01:33 PM |
| and how would you make the different points have different masses? |
|
|
| Report Abuse |
|
|
|
| 01 Mar 2015 01:35 PM |
| I haven't played with masses, but you can probably multiply a certain points gravity. |
|
|
| Report Abuse |
|
|