The thread seemed to move away from Gernstner waves towards the end, and I’d rather tackle the issue heads on, it did give some insight though. (Not going to lie, mainly the parts in which you were the one to comment, was the only thing of real value)
This is the setup of the bones, where the centered (blue circle) is elevated.
This is the plane set-up;
After triangulation, it looks like the following;
Which makes sense, you can see I drew the outline of the same sequence we’re getting in studio.
So all in all, it looks like this
+---+---+---+---+---+
|\ |\ |\ |\ |\ |
| \ | \ | \ | \ | \ |
| \| \| \| \| \|
+---+---+---+---+---+
|\ |\ |\ |\ |\ |
| \ | \ | \ | \ | \ |
| \| \| \| \| \|
+---+---+---+---+---+
This is the code for positioning my bones; excuse the lack of comments- I’ll add them all later on.
function Water:CalculateBoneDisplacement(Position, Wavelength, Direction, Steepness, Gravity, Offset)
local k = (2 * math.pi) / Wavelength
local a = Steepness/k
local d = Direction.Unit
local c = math.sqrt(Gravity / k)
local f = k * d:Dot(Vector2.new(Position.X, Position.Z)) - c * (tick() + (Offset or 0))
local cosF = math.cos(f)
--Displacement Vectors
local dX = (d.X * (a * cosF))
local dY = a * math.sin(f)
local dZ = ( d.Y * (a * cosF))
return Vector3.new(dX,dY,dZ)
end
function Water:CalculateDisplacementFromOrigin(Origin)
local DisplacementA = self:CalculateBoneDisplacement(Origin, 15, Vector2.new(1, 0), 0.3, 1.3)
local DisplacementB = self:CalculateBoneDisplacement(Origin, 12, Vector2.new(2, .4), 0.4, 1.5)
local DisplacementC = self:CalculateBoneDisplacement(Origin, 12, Vector2.new(0, 1), 0.3, 1.5)
local Displacement = DisplacementA + DisplacementB + DisplacementC
return Displacement
end
function Water:UpdateSingularBone(Bone)
local CachedBone = Bones[Bone] or {Origin = Bone.WorldPosition};
local Origin = CachedBone.Origin
local Displacement = self:CalculateDisplacementFromOrigin(Origin)
Bone.WorldPosition = Origin + Vector3.new(0, Displacement.Y, 0)
Bones[Bone] = CachedBone
end
function Water:Update()
for _, Bone in pairs(self.Plane:GetChildren()) do
if not Bone:IsA("Bone") then continue end
self:UpdateSingularBone(Bone)
end
--local Wave1 = self:Wave(Origin, script.A.Length.Value, Vector2.new(1, 0), script.A.Steepness.Value, script.A.Gravity.Value, tick()) -- 15 | .8
end
Where the RunService loop handles the rest, including the positioning of the part.
function Water:Start()
Distributor = self:GetDistributor()
ServiceProvider = Distributor:GetServiceProvider()
CollectionService = ServiceProvider:GetService("CollectionService")
RunService = ServiceProvider:GetService("RunService")
local Planes = CollectionService:GetTagged("Water")
for _, Plane in pairs(Planes) do
table.insert(Cache, Water.new(Plane))
end
local CheckOrigin = workspace.CheckThis.Position
RunService.RenderStepped:Connect(function()
local CheckDisplacement = self:CalculateDisplacementFromOrigin(CheckOrigin)
workspace.CheckThis.Position = CheckOrigin + Vector3.new(0, CheckDisplacement.Y, 0)
for _, Water in pairs(Cache) do
Water:Update()
end
end)
end