summaryrefslogtreecommitdiffstats
path: root/trochoid_math.cginc
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-01-14 21:01:26 -0800
committeryum <yum.food.vr@gmail.com>2025-01-14 21:01:28 -0800
commit333562544ef1b71a7a4d7ce1ece533bef98ce0da (patch)
treec9620943f8a772db0da777e1aa759b30adb17925 /trochoid_math.cginc
parentab441140208d6dd8317f328f40a25c6054f1a304 (diff)
im going to kill myself
attempt to fix hypotrochoid normals key insight is that multiplying normal by transpose(invert(jacobian)) of transform should work, but it fucking doesn't
Diffstat (limited to 'trochoid_math.cginc')
-rw-r--r--trochoid_math.cginc195
1 files changed, 132 insertions, 63 deletions
diff --git a/trochoid_math.cginc b/trochoid_math.cginc
index 7a4e7e2..dd6d69c 100644
--- a/trochoid_math.cginc
+++ b/trochoid_math.cginc
@@ -6,83 +6,152 @@
#if defined(_TROCHOID)
-float3 trochoid_map(float theta, float r0, float3 vert_z)
+#define TROCH_POSITION_SCALE 0.1
+#define TROCH_Z_THETA_SCALE 0.0002
+#define TROCH_EPSILON 1e-5
+
+float3 cyl2_to_troch_map(float3 pos)
{
- r0 *= r0;
- r0 *= 100;
+ float theta = pos.x;
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 * R) + d * cos((R - r) * theta * R / r)) * pos.y * TROCH_POSITION_SCALE;
+ float y = ((R - r) * sin(theta * R) - d * sin((R - r) * theta * R / r)) * pos.y * TROCH_POSITION_SCALE;
+ float z = (pos.z + cos(theta * R * 5) * TROCH_POSITION_SCALE + theta * R * TROCH_Z_THETA_SCALE) * pos.y;
- 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;
+ return float3(x, y, z);
+}
- float3 result = float3(x, y, z) * r0;
- result.xy *= 0.1;
- return result;
+float3 cyl_to_cyl2_map(float3 v)
+{
+ return float3(v.x, pow(v.y, _Trochoid_Radius_Power) * _Trochoid_Radius_Scale, v.z * _Trochoid_Height_Scale);
}
-float trochoid_normal(float3 objPos, float2 uv)
+float3 cart_to_cyl_map(float3 v)
{
- 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);
+ return float3(atan2(v.y, v.x), length(v.xy), v.z);
+}
+
+// Compute partial derivatives of trochoid function with respect to cylindrical coordinates
+float3x3 cyl2_to_troch_jacobian(float3 pos)
+{
+ float theta = pos.x;
+
+ float R = _Trochoid_R;
+ float r = _Trochoid_r;
+ float d = _Trochoid_d;
+
+#if 1
+ float3 df_dt = float3(
+ ((R * (r - R) * (d * sin(R * theta * (R - r) / r) + r * sin(R * theta))) / r) * pos.y * TROCH_POSITION_SCALE,
+ ((R * (r - R) * (-d * cos(R * theta * (R - r) / r) + r * cos(R * theta))) / r) * pos.y * TROCH_POSITION_SCALE,
+ (-R * 5 * sin(theta * R * 5) * TROCH_POSITION_SCALE + R * TROCH_Z_THETA_SCALE) * pos.y);
+ float3 df_dr = float3(
+ ((R - r) * cos(theta * R) + d * cos((R - r) * theta * R / r)) * TROCH_POSITION_SCALE,
+ ((R - r) * sin(theta * R) - d * sin((R - r) * theta * R / r)) * TROCH_POSITION_SCALE,
+ (pos.z + cos(theta * R * 5) * TROCH_POSITION_SCALE + theta * R * TROCH_Z_THETA_SCALE));
+ float3 df_dz = float3(
+ 0,
+ 0,
+ pos.y);
+#else
+ float3 df_dt = (cyl2_to_troch_map(pos + float3(TROCH_EPSILON, 0, 0)) - cyl2_to_troch_map(pos - float3(TROCH_EPSILON, 0, 0))) / (2 * TROCH_EPSILON);
+ float3 df_dr = (cyl2_to_troch_map(pos + float3(0, TROCH_EPSILON, 0)) - cyl2_to_troch_map(pos - float3(0, TROCH_EPSILON, 0))) / (2 * TROCH_EPSILON);
+ float3 df_dz = (cyl2_to_troch_map(pos + float3(0, 0, TROCH_EPSILON)) - cyl2_to_troch_map(pos - float3(0, 0, TROCH_EPSILON))) / (2 * TROCH_EPSILON);
+#endif
+ float3x3 jacobian_cyl;
+ jacobian_cyl[0] = df_dt;
+ jacobian_cyl[1] = df_dr;
+ jacobian_cyl[2] = df_dz;
+ return transpose(jacobian_cyl);
+}
+
+float3x3 cyl_to_cyl2_jacobian(float3 pos)
+{
+ // f(x, y, z) = <x, (y^_Trochoid_Radius_Power) * _Trochoid_Radius_Scale, z * _Trochoid_Height_Scale>
+#if 1
+ float3 df_dx = float3(1, 0, 0);
+ float3 df_dy = float3(0, _Trochoid_Radius_Power * pow(pos.y, _Trochoid_Radius_Power - 1) * _Trochoid_Radius_Scale, 0);
+ float3 df_dz = float3(0, 0, _Trochoid_Height_Scale);
+#else
+ float3 df_dx = (cyl_to_cyl2_map(pos + float3(TROCH_EPSILON, 0, 0)) - cyl_to_cyl2_map(pos - float3(TROCH_EPSILON, 0, 0))) / (2 * TROCH_EPSILON);
+ float3 df_dy = (cyl_to_cyl2_map(pos + float3(0, TROCH_EPSILON, 0)) - cyl_to_cyl2_map(pos - float3(0, TROCH_EPSILON, 0))) / (2 * TROCH_EPSILON);
+ float3 df_dz = (cyl_to_cyl2_map(pos + float3(0, 0, TROCH_EPSILON)) - cyl_to_cyl2_map(pos - float3(0, 0, TROCH_EPSILON))) / (2 * TROCH_EPSILON);
+#endif
+ float3x3 jacobian_cyl_to_cyl2;
+ jacobian_cyl_to_cyl2[0] = df_dx;
+ jacobian_cyl_to_cyl2[1] = df_dy;
+ jacobian_cyl_to_cyl2[2] = df_dz;
+ return transpose(jacobian_cyl_to_cyl2);
+}
+
+// Compute partial derivatives of transform from cartesian to cylindrical coordinates
+float3x3 cart_to_cyl_jacobian(float3 pos)
+{
+ // Compute partial derivatives of transform from cartesian to cylindrical coordinates
+ // return float3(atan2(v.y, v.x), length(v.xy), v.z);
+ // theta = atan2(y, x)
+#if 1
+ float3 dtheta_dcart = float3(
+ -pos.y / dot(pos.xy, pos.xy),
+ pos.x / dot(pos.xy, pos.xy),
+ 0);
+#else
+ float3 dtheta_dcart = (cart_to_cyl_map(pos + float3(TROCH_EPSILON, 0, 0)) - cart_to_cyl_map(pos - float3(TROCH_EPSILON, 0, 0))) / (2 * TROCH_EPSILON);
+#endif
+
+ // radius = (x^2 + y^2)^(1/2)
+#if 1
+ float3 dr_dcart = float3(
+ pos.x / sqrt(pos.x * pos.x + pos.y * pos.y),
+ pos.y / sqrt(pos.x * pos.x + pos.y * pos.y),
+ 0);
+#else
+ float3 dr_dcart = (cart_to_cyl_map(pos + float3(0, TROCH_EPSILON, 0)) - cart_to_cyl_map(pos - float3(0, TROCH_EPSILON, 0))) / (2 * TROCH_EPSILON);
+#endif
+
+#if 1
+ float3 dz_dcart = float3(
+ 0,
+ 0,
+ 1);
+#else
+ float3 dz_dcart = (cart_to_cyl_map(pos + float3(0, 0, TROCH_EPSILON)) - cart_to_cyl_map(pos - float3(0, 0, TROCH_EPSILON))) / (2 * TROCH_EPSILON);
+#endif
+ float3x3 jacobian_cart_to_cyl;
+ jacobian_cart_to_cyl[0] = dtheta_dcart;
+ jacobian_cart_to_cyl[1] = dr_dcart;
+ jacobian_cart_to_cyl[2] = dz_dcart;
+ return transpose(jacobian_cart_to_cyl);
+}
+
+float3x3 invert(float3x3 m)
+{
+ float det = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1])
+ - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0])
+ + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
+
+ float3x3 adj;
+ adj[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]);
+ adj[0][1] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]);
+ adj[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]);
+
+ adj[1][0] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]);
+ adj[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]);
+ adj[1][2] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]);
+
+ adj[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
+ adj[2][1] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]);
+ adj[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]);
+
+ return adj * (1.0 / det);
}
#endif // _TROCHOID
#endif // __TROCHOID_MATH
+