# How to find normal on wave

I want to add the method ‘wave:getNormal(x, z, t)’, where x and z are coordinates and t is the time in seconds. The method should return a unit normal of a given point on the mathematical function specified in ‘wave:getValue(x, z, t)’. ‘self.CONFIG’ contains some wave parameters like HEIGHT and LENGTH. This is the relevant code:

``````local wave = {}

-- This method is used for giving a direction to the wave
function wave:getP(x, z, t)
return Vector2.new(Vector2.new(x, z):Dot(self.config.DIRECTION), Vector2.new(z, x):Dot(self.config.DIRECTION)) * math.pi / self.config.LENGTH
end

-- This method is used to get the height of the wave
function wave:getValue(x, z, t)
local LENGTH = self.config.LENGTH

local p = self:getP(x, z, t)
-- This is the maths function that should be related to wave:getNormal(x, z, t)
return math.sin(p.x - t * self.config.SPEED) * math.sin((p.x + p.y) / 5) * self.config.HEIGHT + self.config.BIAS
end

function wave:getNormal(x, z, t)
-- Not sure how to calculate this
end
``````

The problem is that I do not know how to calculate the unit normal. All I know is that it has something to do with derivatives and the tangent line of the wave’s maths function. Here is an illustration of what I want to calculate, where the blue part is my wave:

I have tried to mess around with derivatives, but I have come to the conclusion that I do not have enough knowledge about derivatives and vectorial equations.

I should probably post this on a maths forum, but I thought I can at least try to ask it here.

2 Likes

The easiest way would be to just estimate it:

``````function wave:getNormal(x, z, t)
-- some small number
local h = 0.001

-- value at the point
local v = self:getValue(x, z, t)

-- value slightly to the right of the point
local vx = self:getValue(x + h, z, t)

-- value slightly behind the point
local vz = self:getValue(x, z + h, t)

-- vector from v -> v_x
local v_vx = Vector3.new(h, vx - v, 0)

-- vector from v -> v_z
local v_vz = Vector3.new(0, vz - v, h)

-- normal vector
return v_vz:Cross(v_vx).Unit
end
``````

The other way would be to figure out the partial derivative of `wave:getValue` w.r.t `x` and `z` and then your normal is proportional to

``````Vector3.new(dfdx(x, z), 1, dfdz(x, z))
``````

Apparently, according to Normal Vector -- from Wolfram MathWorld

But that sounds hard, and estimating is probably good enough.

2 Likes

Thanks, I will try to implement this and see how it goes. I will mark this as the solution if everything is correct.

I think that I will actually use both methods, since I organized my waves into seperate modules. I can use the approximation if the chosen wave does not have a ‘getNormal’ method.

The + h parts should be - h, but everything seems to work! I will soon make a ‘Cool Creations’ post about my latest project. Then you will be able to revisit your contribution.

1 Like