Нормаль трехмерной волны

Проблема: у меня есть функция, которая вычисляет значение Y (высоту) волны по координатам X и Z. Мне также нужна нормаль в этой точке, то есть нормаль касательной/градиента в этой точке.

Фоновые материалы:

  • Я пытаюсь смоделировать волны океана, чтобы иметь плавучую лодку, на которую воздействуют волны, чтобы она качалась вперед-назад и из стороны в сторону.
  • Это для игры, которую я делаю в единстве для школьного проекта.
  • Я пишу сценарии на C#, но Unity также принимает JavaScript.
  • Вода представляет собой плоскость с несколькими вершинами, поэтому высота каждой вершины вычисляется моим скриптом (эта часть уже сделана).

Что у меня есть до сих пор

using UnityEngine;
using System.Collections;

public class Weather : MonoBehaviour
{   
        //The height of the waves
        public float amplitude = 0.01f;
        //The number of waves
        public float frequency = 50f;
        //The speed the direction of the waves rotate
        public float directionChange;

        // Update is called once per frame, every frame it is rotated a small amount.
        //using transform.rotate allows for easy rotation and reference to its direction with transform.forward is automaticlly normalised.
        void FixedUpdate ()
        {
                //Rotates around the y axis
                transform.RotateAround (transform.position, Vector3.up, directionChange * Time.deltaTime);
        }   

        //Gets the height (y value) of the wave at an (x,z) position. At each frame the amplitude, time, frequency and direction are considered constant so that but these all change with between each frame.
        public float heightAt (float x, float z)
        {
                return amplitude * Mathf.Sin (Time.realtimeSinceStartup + x * frequency * transform.forward.x + z * frequency * transform.forward.z);
        }

        //This needs to use the same function as the heightAt(x, z) method so that the normal at a point can be calculated e.g. the normal at a point on top of the wave would be straight up
        public Vector3 normalAt (float x, float z)
        {
                return Vector3.up;
        }
}

Мое исследование выявило цепное правило, и я пытался [безуспешно] его использовать. У меня возникают трудности с получением нормализованного вектора градиента (чтобы затем я мог получить нормализованный вектор нормали)

Мне нужно найти нормаль, чтобы я мог рассчитать силу плавучести на лодке с помощью узлов, эти узлы могут вычислить силу, приложенную к их родительскому объекту (лодке), проверяя, находятся ли они в воде. Если узел находится над волной, то он приложит к лодке силу гравитации, если под волной, он будет использовать нормаль, чтобы приложить силу, чтобы волны толкали ее.

Надеюсь, я выразился достаточно ясно, чтобы вы поняли. Спасибо за чтение :)


person Bricktron    schedule 30.04.2014    source источник
comment
Вы знаете исчисление? градиент x для f(x) = d/dx f(x), градиент y для f(x) = d/dy f(x), где f — уравнение для вашей волны. Это частные производные. После того, как они у вас есть, вы можете нормализовать их, разделив оба компонента на длину (sqrt (x ^ 2 + y ^ 2)). Это нормализованный градиент.   -  person luqui    schedule 30.04.2014
comment
Также Wolfram Alpha знает исчисление ;-)   -  person luqui    schedule 30.04.2014
comment
К сожалению, в моем первом комментарии предполагалось, что x-градиент f(x,y) равен d/dx f(x,y), y-градиент равен d/dy f(x,y). Волна является функцией обеих переменных.   -  person luqui    schedule 30.04.2014


Ответы (1)


Хм... Должно быть так:

public Vector3 normalAt (float x, float z)
{
    float argument = Time.realtimeSinceStartup + x * frequency * transform.forward.x + z * frequency * transform.forward.z;
    float nx = amplitude * frequency * transform.forward.x * Mathf.Cos(argument);
    float ny = -1.0f;
    float nz = amplitude * frequency * transform.forward.z * Mathf.Cos(argument);
    return new Vector3(nx, ny, nz).normalized; // Not sure about sign. Maybe you need to multiply the result by -1.
}
person Sergey Krusch    schedule 30.04.2014
comment
Да, это все. Нужно умножить на -1. - person Bricktron; 01.05.2014