Después de leer la respuesta de peachykeen y hacer algunas (más) investigaciones en Internet, he encontrado la siguiente solución para mí.
Con mi aplicación de ruido Perlin, utilizando un intervalo de valores de [0,0 .. 1,0] para el rayo nodos ruta de trabajo mejor, pasando el valor (doble) M/(doble) N para el nodo M al Función de ruido Perlin.
Para tener una función de ruido F 'devuelve el mismo valor para el nodo 0 y el nodo N-1, se puede aplicar la siguiente fórmula: F' (M) = ((M - N) * F (N) + N * F (N - M))/M. Para que las desviaciones de la trayectoria del rayo comiencen y finalicen con 0, simplemente necesita restar F '(0) de todos los desplazamientos de la trayectoria del rayo después de haber calculado la trayectoria.
Para aleatorizar la trayectoria del rayo, antes de calcular los desplazamientos para cada nodo, se puede calcular y agregar una compensación aleatoria R a los valores pasados a la función de ruido para que el nodo O = F '(N + R). Para animar un rayo, se deben calcular dos trayectorias de rayo (cuadro de inicio y final), y luego cada vértice de trayecto tiene que estar activado entre su posición inicial y final. Una vez que se ha alcanzado el marco final, el marco final se convierte en el marco inicial y se calcula un nuevo marco final. Para una ruta 3D, para cada nodo de ruta N se pueden calcular dos vectores de desplazamiento que son perpendiculares a la ruta en el nodo N y entre sí, y se pueden escalar con dos valores de ruido 1D Perlin para visualizar la posición del nodo desde la posición de inicio hasta el final . Eso puede ser más barato que hacer ruido 3D Perlin y funciona bastante bien en mi aplicación.
Aquí es mi implementación de ruido estándar 1D Perlin como referencia (algunas cosas es virtual porque yo estoy usando esto como base para la mejora de ruido Perlin, lo que permite utilizar el ruido estándar o mejorado Perlin en una aplicación de patrón de estrategia. el código se ha simplificado un tanto así para que sea más concisa para publicarla aquí):
archivo de cabecera:
#ifndef __PERLIN_H
#define __PERLIN_H
class CPerlin {
private:
int m_randomize;
protected:
double m_amplitude;
double m_persistence;
int m_octaves;
public:
virtual void Setup (double amplitude, double persistence, int octaves, int randomize = -1);
double ComputeNoise (double x);
protected:
double LinearInterpolate (double a, double b, double x);
double CosineInterpolate (double a, double b, double x);
double CubicInterpolate (double v0, double v1, double v2, double v3, double x);
double Noise (int v);
double SmoothedNoise (int x);
virtual double InterpolatedNoise (double x);
};
#endif //__PERLIN_H
Implementación:
#include <math.h>
#include <stdlib.h>
#include "perlin.h"
#define INTERPOLATION_METHOD 1
#ifndef Pi
# define Pi 3.141592653589793240
#endif
inline double CPerlin::Noise (int n) {
n = (n << 13)^n;
return 1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff)/1073741824.0;
}
double CPerlin::LinearInterpolate (double a, double b, double x) {
return a * (1.0 - x) + b * x;
}
double CPerlin::CosineInterpolate (double a, double b, double x) {
double f = (1.0 - cos (x * Pi)) * 0.5;
return a * (1.0 - f) + b * f;
}
double CPerlin::CubicInterpolate (double v0, double v1, double v2, double v3, double x) {
double p = (v3 - v2) - (v0 - v1);
double x2 = x * x;
return v1 + (v2 - v0) * x + (v0 - v1 - p) * x2 + p * x2 * x;
}
double CPerlin::SmoothedNoise (int v) {
return Noise (v)/2 + Noise (v-1)/4 + Noise (v+1)/4;
}
int FastFloor (double v) { return (int) ((v < 0) ? v - 1 : v; }
double CPerlin::InterpolatedNoise (double v) {
int i = FastFloor (v);
double v1 = SmoothedNoise (i);
double v2 = SmoothedNoise (i + 1);
#if INTERPOLATION_METHOD == 2
double v0 = SmoothedNoise (i - 1);
double v3 = SmoothedNoise (i + 2);
return CubicInterpolate (v0, v1, v2, v3, v - i);
#elif INTERPOLATION_METHOD == 1
return CosineInterpolate (v1, v2, v - i);
#else
return LinearInterpolate (v1, v2, v - i);
#endif
}
double CPerlin::ComputeNoise (double v) {
double total = 0, amplitude = m_amplitude, frequency = 1.0;
v += m_randomize;
for (int i = 0; i < m_octaves; i++) {
total += InterpolatedNoise (v * frequency) * amplitude;
frequency *= 2.0;
amplitude *= m_persistence;
}
return total;
}
void CPerlin::Setup (double amplitude, double persistence, int octaves, int randomize) {
m_amplitude = (amplitude > 0.0) ? amplitude : 1.0;
m_persistence = (persistence > 0.0) ? persistence : 2.0/3.0;
m_octaves = (octaves > 0) ? octaves : 6;
m_randomize = (randomize < 0) ? (rand() * rand()) & 0xFFFF : randomize;
}
Esta pregunta es genial. – sharptooth
http://www.noisemachine.com/talk1/23.html –