So I am working on a wave/ocean system and I’m using this module made by @iamtryingtofindname: Realistic Oceans Using Mesh Deformation!

When I was testing it, I noticed my waves are very jagged and have very sharp lines as you can see in the video below:

I tried covering it up using the built-in perlin noise feature but it didn’t really work as those jagged lines are still very visible. I feel like the issue could probably be the plane with the bones which I might’ve messed up bc I did do it myself without knowing much about bones and rigging.

I want to achieve smooth waves similar to @tyridge77’s system here: Seamless, endless, and performant custom water using skinned meshes and PBR

But I honestly don’t know how to go about that. Here is the code the does the math calculations to determine the waves:

```
-- local script
local Wave = require(script.Wave)
local Randomness = {
WaveLength = 70,
Gravity = 1.5,
Direction = Vector2.new(1,0), -- It is 0, 0, so it will use the perlin noise algorithm to make random waves for me
--PushPoint = workspace.Wave1.PushPoint, -- Alternative to Direction, the wave's direction will always push away from the part.
Steepness = 0.6,
TimeModifier = 4,
MaxDistance = 1500,
}
local Wave1 = Wave.new(workspace.ocean_plane3.Plane, Randomness --[[Direction]])
Wave1:ConnectRenderStepped()
-- module made by @iamtryingtofindname (just the calculation functions)
local function Gerstner(Position: Vector3,Wavelength: number,Direction: Vector2,Steepness: number,Gravity: number,Time: number)
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 * Time
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
local function GetDirection(Settings,WorldPos)
local Direction = Settings.Direction
local PushPoint = Settings.PushPoint
if PushPoint then
local PartPos = nil
if PushPoint:IsA("Attachment") then
PartPos = PushPoint.WorldPosition
elseif PushPoint:IsA("BasePart") then
PartPos = PushPoint.Position
else
warn("Invalid class for FollowPart, must be BasePart or Attachment")
return
end
Direction = (PartPos - WorldPos).Unit
Direction = Vector2.new(Direction.X, Direction.Z)
end
return Direction
end
function Wave:Update()
for _,v in pairs(self._bones) do
local WorldPos = v.WorldPosition
local Settings = self._settings
local Direction = Settings.Direction
if Direction == EmptyVector2 then
-- Use Perlin Noise
local Noise = self._noise[v]
local NoiseX = Noise and self._noise[v].X
local NoiseZ = Noise and self._noise[v].Z
local NoiseModifier = 1 -- If you want more of a consistent direction, change this number to something bigger
if not Noise then
self._noise[v] = {}
-- Uses perlin noise to generate smooth transitions between random directions in the waves
NoiseX = math_noise(WorldPos.X/NoiseModifier,WorldPos.Z/NoiseModifier,1)
NoiseZ = math_noise(WorldPos.X/NoiseModifier,WorldPos.Z/NoiseModifier,0)
self._noise[v].X = NoiseX
self._noise[v].Z = NoiseZ
end
Direction = Vector2.new(NoiseX,NoiseZ)
else
Direction = GetDirection(Settings,WorldPos)
end
local cframe1 = newCFrame(Gerstner(WorldPos,Settings.WaveLength,Direction,Settings.Steepness,Settings.Gravity,self._time))
v.Transform = cframe1
end
end
```

Any help would be greatly appreciated.