summaryrefslogtreecommitdiffstats
path: root/trochoid_math.cginc
blob: 7a4e7e2f107867f6976015b99399c90ed73b37ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "globals.cginc"
#include "math.cginc"

#ifndef __TROCHOID_MATH
#define __TROCHOID_MATH

#if defined(_TROCHOID)

float3 trochoid_map(float theta, float r0, float3 vert_z)
{
  r0 *= r0;
  r0 *= 100;

  float R = _Trochoid_R;
  float r = _Trochoid_r;
  float d = _Trochoid_d;

  theta *= max(R, r);
  float theta_t = theta + _Time[2];

  float x = (R - r) * cos(theta_t) + d * cos((R - r) * theta_t / r);
  float y = (R - r) * sin(theta_t) - d * sin((R - r) * theta_t / r);
  float z = vert_z + cos(theta_t * 5) * .1 + theta * .0002;

  float3 result = float3(x, y, z) * r0;
  result.xy *= 0.1;
  return result;
}

float trochoid_normal(float3 objPos, float2 uv)
{
  float theta = uv.x * TAU;
  float r0 = length(objPos.xyz);

  float x = objPos.x;
  float y = objPos.y;
  float z = objPos.z;

  float e = 5E-2;
  float small_step = 1E-2 * e;
  float du_dt = (trochoid_map(theta + small_step, r0, z) - trochoid_map(theta - small_step, r0, z)) / small_step;
  small_step = 1E-4 * e;
  float du_dr = (trochoid_map(theta, r0 + small_step, z) - trochoid_map(theta, r0 - small_step, z)) / small_step;
  small_step = 1E-5 * e;
  float du_dz = (trochoid_map(theta, r0, z + small_step) - trochoid_map(theta, r0, z - small_step)) / small_step;

  // U(T(x, y, z), R(x, y, z), Z(x, y, z))
  // T(x, y, z) = atan2(y, x)
  // R(x, y, z) = length(float3(x, y, z))
  // Z(x, y, z) = z
  // U(a, b, c) = trochoid_map(a, b, c)
  // dU/dx = dU/dT dT/dx + dU/dR dR/dx + dU/dZ dZ/dx
  // dU/dy = dU/dT dT/dy + dU/dR dR/dy + dU/dZ dZ/dy
  // dU/dz = dU/dT dT/dz + dU/dR dR/dz + dU/dZ dZ/dz
  // dT/dx = d/dx atan2(y, x) = -y / (x**2 + y**2)
  // dT/dy = d/dx atan2(y, x) = x / (x**2 + y**2)
  // dT/dz = d/dz atan2(y, x) = 0
  // dR/dx = d/dx sqrt(x**2 + y**2 + z**2) = x / sqrt(x**2 + y**2 + z**2)
  // dR/dy = d/dy sqrt(x**2 + y**2 + z**2) = y / sqrt(x**2 + y**2 + z**2)
  // dR/dz = d/dy sqrt(x**2 + y**2 + z**2) = z / sqrt(x**2 + y**2 + z**2)
  // dZ/dx = 0
  // dZ/dy = 0
  // dZ/dz = 1
  float xy_norm = sqrt(x * x + y * y);
  float dt_dx = -y / xy_norm;
  float dt_dy = x / xy_norm;
  float dt_dz = 0;
  float xyz_norm = sqrt(x * x + y * y + z * z);
  float dr_dx = x / xyz_norm;
  float dr_dy = y / xyz_norm;
  float dr_dz = z / xyz_norm;
  float dz_dx = 0;
  float dz_dy = 0;
  float dz_dz = 1;

  float3 normal =
    normalize(
        float3(
          du_dt * dt_dx + du_dr * dr_dx + du_dz * dz_dx,
          du_dt * dt_dy + du_dr * dr_dy + du_dz * dz_dy,
          du_dt * dt_dz + du_dr * dr_dz + du_dz * dz_dz));
  return UnityObjectToWorldNormal(normal);
}

#endif  // _TROCHOID

#endif  // __TROCHOID_MATH