- Home /

# Sine Wave mesh deform with different directions

I'm creating a sea based on a plane that I deform with a sine wave (cycling through the vertices and offsetting the y value). Code:

```
void CalculateWaves ()
{
if (m_BaseHeight == null)
m_BaseHeight = m_WaterPlane.vertices;
Vector3[] WaterVertices = new Vector3[m_BaseHeight.Length];
for (int i=0; i< WaterVertices.Length; i++)
{
Vector3 Vertex = m_BaseHeight[i];
Vertex.y += Mathf.Sin(Time.time * m_WaveSpeed+ m_BaseHeight[i].x+ m_BaseHeight[i].y + m_BaseHeight[i].z)*m_WaveScale;
WaterVertices[i] = Vertex;
}
m_WaterPlane.vertices = WaterVertices;
m_WaterPlane.RecalculateNormals ();
```

However, this only allows the sine wave to go diagonally over the plane from top right to bottom left (and reverse if you make m_WaveSpeed negative). Ideally I'd like this to be controlled by a vector, so I can later create a wind class that provides the input.

I'm also looking for a way to use a noisemap texture to influence these waves. I haven't tried this out yet, but my idea would be basically this:

```
float incrementAmount= texture.getpixels.length/mesh.getvertices.length;
int j=0;
for (int i=0; i<vertices; i++)
{
vertices[i].y+=pixels[j].r;
j+=incrementAmount;
}
```

Is this a good way, or are there more efficient/accurate ways to go about this?

Scratch the second part of this question, I found out that with a few tweaks my idea works and seems to run fluently as well.

**Answer** by Bunny83
·
Jul 13, 2014 at 03:26 PM

Well, at the moment you use the local position within the mesh to offset your sin function. Since you add x and z together you get the diagonal behaviour since it doesn't matter if you increase x or z.

All you have to do is rotate the system around the y axis:

```
Quaternion rotation;
void CalculateWaves ()
{
if (m_BaseHeight == null)
m_BaseHeight = m_WaterPlane.vertices;
Vector3[] WaterVertices = new Vector3[m_BaseHeight.Length];
for (int i=0; i< WaterVertices.Length; i++)
{
Vector3 Vertex = m_BaseHeight[i];
Vector3 dir = rotation * Vertex;
Vertex.y += Mathf.Sin(Time.time * m_WaveSpeed+ dir.x + dir.y + dir.z) * m_WaveScale;
WaterVertices[i] = Vertex;
}
m_WaterPlane.vertices = WaterVertices;
m_WaterPlane.RecalculateNormals ();
}
```

*edit*

I've just played around a bit and extended my test script a bit ;) Now you can have 1 or multiple wave systems overlapping. The test script is designed for **two** systems at the moment since i've hardcoded the direction setting:

```
// MeshWave.cs
// C#
using UnityEngine;
using System.Collections;
public class MeshWave : MonoBehaviour
{
[System.Serializable]
public class WaveSystem
{
private Quaternion m_Rotation;
private Vector3 m_Direction;
public float Length;
public float Speed;
public float Scale;
public Vector3 Direction
{
get {return m_Direction;}
set
{
m_Direction = value.normalized;
m_Rotation = Quaternion.Inverse(Quaternion.LookRotation(-m_Direction));
}
}
public Vector3 ApplyHeight(Vector3 aPos)
{
Vector3 dir = m_Rotation * aPos;
if (Length != 0)
dir.z *= 1.0f/Length;
aPos.y += Mathf.Sin(Time.time * Speed+ dir.z ) * Scale;
return aPos;
}
}
public Transform Target1;
public Transform Target2;
public WaveSystem[] waves;
Vector3[] m_BaseHeight;
Mesh m_WaterPlane;
void CalculateWaves ()
{
waves[0].Direction = Target1.position - transform.position;
waves[1].Direction = Target2.position - transform.position;
if (m_BaseHeight == null)
m_BaseHeight = m_WaterPlane.vertices;
Vector3[] WaterVertices = new Vector3[m_BaseHeight.Length];
for (int i=0; i< WaterVertices.Length; i++)
{
Vector3 Vertex = m_BaseHeight[i];
foreach(var W in waves)
{
Vertex = W.ApplyHeight(Vertex);
}
WaterVertices[i] = Vertex;
}
m_WaterPlane.vertices = WaterVertices;
m_WaterPlane.RecalculateNormals ();
}
void Start ()
{
m_WaterPlane = GetComponent<MeshFilter>().mesh;
}
void Update ()
{
CalculateWaves();
}
}
```

I just tried out your suggestion, but it doesn't do what you suggest. It actually scales the frequency of the sine wave, causing more or less ripples depending on the value, (which is another feature I was looking for, so props to that at least) but it doesn't change the direction unfortunately.

Uhm, are you sure you set a rotation around the y axis? Something like:

```
rotation = Quaternion.Euler(0, SomeAngle, 0);
```

Scratch that last comment, I didn't notice you used Quaternions there. Now it sorta works when I make this variable public and mess around with it at runtime. However it gives a lot of ugly results and I'm unsure how to properly control this, especially considering I'd like to use a directional vector as input later. It also seems to break my tiling system under certain angles, where I use a vertex's "world coordinate" to calculate the wave. Code here: `Vector3 Vertex = m_BaseHeight[i]; Vector3 Direction = m_Rotation*Vertex; float XCoord=(Direction.x+gameObject.transform.position.x)*m_Frequency; float ZCoord=(Direction.z+gameObject.transform.position.z)*m_Frequency; Vertex.y += Mathf.Sin(Time.time * m_WaveSpeed+ XCoord+ Vertex.y + ZCoord)*m_WaveScale;`

Any ideas for a proper conversion and control?

I just tried it with the built-in plane in Unity and it works as expected. If you also want to control the wave lenth you just need to scale your vector. Here's my test script:

** edit** I just read that you want to use a vector as wave direction. Well, all you have to do is using Quaternion.LookRotation. As we rotate actually the vertices we need to invert the rotation. I've edited my script below. I use a Target gameobject to specify the direction but you can set any direction vector as "D".

** 2. edit** Just removed my sample script as i added a more advanced version to my answer. Long comments are always irritating for readers.

Sorry for the late reply here.

Thanks for your awesome help so far, but I still have a problem. I've reworked your solution to fit my existing code and needs, but right now whenever I alter the frequency of the waves it seems to interfere with the direction, and vice versa. Since frequency will change a lot because it is affected by the wind's strength, this becomes rather problematic. Perhaps there's just an error I'm overlooking, but here's the code none the less for cross checking.

```
void CalculateWaves ()
{
if (m_BaseHeight == null)
m_BaseHeight = m_WaterPlane.vertices;
Vector3[] WaterVertices = new Vector3[m_BaseHeight.Length];
for (int i=0; i< WaterVertices.Length; i++)
{
Vector3 Vertex = m_BaseHeight[i];
Vector3 TransformedVertex=Vertex+gameObject.transform.position;
Vector3 Direction = m_Rotation*TransformedVertex;
if(m_Frequency!=0)
Direction.z*=1.0f/m_Frequency;
Vertex.y += Mathf.Sin(Time.time * m_WaveSpeed+ Direction.z)*m_WaveScale;
```

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.