Hey everybody,
So I believe the title says it all. So what I want to do is that on my mesh deformation ocean I want to align the parts to the waves. I got position aligned successfully, but I have no clue on how to align the orientation. https://streamable.com/hqpcqt
Here’s the current gerstner wave function am using:
local function GerstnerWave(SamplePosition, Wavelength, Direction, Steepness, Gravity, SampleTick)
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(SamplePosition.X, SamplePosition.Z)) - c * SampleTick
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
Then I just add the displacement vector the function returns to the original position of the bone which I cache in a table at the start of the script.
for i, bone in pairs(workspace.Ocean.Plane:GetChildren()) do
if bone:IsA("Bone") then
origPosTable[bone] = bone.Position
end
end
game:GetService("RunService").Heartbeat:Connect(function()
speedCounter += script:GetAttribute("WaveSpeed")
-- simulate the "waves"
for i, bone in pairs(workspace.Ocean.Plane:GetChildren()) do
if bone:IsA("Bone") then
local displacement = GerstnerWave(bone.WorldPosition, script:GetAttribute("WaveLength"), script:GetAttribute("Direction"), script:GetAttribute("Steepness"), script:GetAttribute("Gravity"), speedCounter)
bone.Position = origPosTable[bone] + displacement
end
end
end)
What I tried:
Using attachments, positioning them according to the wave at their point and then calculating the angle between them
Add the displacement returned to the orientation too (I knew it wouldn’t work but was just testing)
But nothing worked.
While replying please give me some resources and not the full script, I want to learn new things, you can also tell me what functions/things I would have to use for this, but please keep in mind am just in 8th grade so I dont know much about these things.
Ideally you should use physics to simulate buoyancy.
But if you want to rigidly calculate the surface of the water you can use three points (three sample positions) to form a plane.
This plane will have a normal vector which you can use to align the part up vector with the generated normal vector, thus “aligning orientation” to the ocean
Raycasting towards the water will return the point of impact as well as the surface normal. The surface normal points perpendicular to the surface of the wave.
Here’s one guy’s take on it and a slight fix I gave him.
When you move the bones of a deformed part it wont respond to raycasts and If you raycast down it’ll hit the original position of the ocean, so it assumes that the ocean is flat and hence results are not good. I’ve tried this before too.
I literally saw that video yesterday but unfortunately I could understand only half of the things since it was all in c++. I’ll try to give it another look today.
I’ve thought of a way to add 4 invisible parts in the main part (which will be named “bow”, “stern”, “port”, “starboard”. bow is placed at the front tip, stern at the rear tip and port and starboard at left and right tips), calculate the water height at each part and then get the angle, then set it in the orientation. May/may not work. I think you mean something similar to this?
Here’s what I’m using for angle calculation:
local function angleBetweenVectors(a: Vector3, b: Vector3)
return math.acos(a:Dot(b) / (a.Magnitude * b.Magnitude))
end
That uses raycasting, it won’t work.
Once you move the mesh bones, the physics engine still takes into account the original position of the ocean, which is flat, so if you drop a part it will not stay above the waves but it’d rather fall down and hit the original “flat” ocean. If you know what I mean. Raycasts and collisions will always react to the flat original position and hence you need to calculate everything rigidly.
Part of the resource uses raycasting to find three points on the surface to rotate towards that surface.
I’m saying you can substitute the raycasting with the function that calculates the position points for you already.
--the ground orientation math
--//Ground orientation math//--
local down = -10*hrp.CFrame.upVector
local r1, r2, r3 = Ray.new(hrp.CFrame:PointToWorldSpace(p1.Position), down), Ray.new(hrp.CFrame:PointToWorldSpace(p2.Position), down), Ray.new(hrp.CFrame:PointToWorldSpace(p3.Position), down)
local o1, p1 = workspace:FindPartOnRay(r1, model)
local o2, p2 = workspace:FindPartOnRay(r2, model)
local o3, p3 = workspace:FindPartOnRay(r3, model)
local upVector = (o1 and o2 and o3) == nil and bg.CFrame.UpVector or -((p1-p2):Cross(p3-p2)).Unit
--input into body gyro later on
local rightVector = (bg.CFrame.lookVector:Cross(upVector)).Unit
local pos = hrp.Position
bg.CFrame = CFrame.fromMatrix(pos, rightVector, upVector)*CFrame.Angles(0, TurnSpeed*(a-d), 0)
However instead of raycasting you can just replace it with the function to find p1,p2,p3 point 1,2, and 3.
local p1 = GerstnerWave(--something)
local p2 = GerstnerWave(--something)
local p3 = GerstnerWave(--something)
local upVector =-((p1-p2):Cross(p3-p2)).Unit
This is plane maths in order to find the upvector of the plane.
I guess it’s someting like yours with getting an angle, but more concrete as you haven’t mentioned how you will get the angle and convert it to an orientation value or such.
I’ll admit that I know Jack all about mesh deformation, but in the post I linked he was indeed using ray casting and mesh deformation and he claimed that it worked.
As I said, it didnt work. Just tried it. Printing the surface normal of the raycast spams Vector3.new(0, 1, 0 in the output because the water is using mesh deformation. I saw your post and its interesting how its working for that guy. Here’s how am doing it:
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
raycastParams.FilterDescendantsInstances = {workspace.Ocean}
raycastParams.IgnoreWater = true
local direction = v.CFrame.UpVector * -10
local raycast = workspace:Raycast(v.Position, direction, raycastParams)
if raycast then
print(raycast.Normal)
print(raycast.Position)
end
To make sure my raycast is hitting the water I did print(raycast.Instance:GetFullName()) and it printed workspace.Ocean.Plane too. The only problem is to get the SurfaceNormal.