132 lines
4.7 KiB
C#
132 lines
4.7 KiB
C#
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
public class Gravity : MonoBehaviour
|
|
{
|
|
public float GlobalGravityMultiplier;
|
|
public GravityForceMode ForceMode = GravityForceMode.Gradient;
|
|
public float GradientStepSize = .01f;
|
|
public float NormalMultiplier = 100f;
|
|
public List<GravityObject> GravityObjects = new List<GravityObject>();
|
|
|
|
private static Gravity _instance;
|
|
|
|
public static Gravity Instance
|
|
{
|
|
get
|
|
{
|
|
if (_instance != null)
|
|
return _instance;
|
|
|
|
_instance = FindAnyObjectByType<Gravity>();
|
|
return _instance;
|
|
}
|
|
}
|
|
|
|
public static float GetHeight(Vector2 position)
|
|
{
|
|
float result = 0;
|
|
foreach (var go in Instance.GravityObjects)
|
|
{
|
|
if (((Vector2) go.transform.InverseTransformPoint(position.Flatland())).sqrMagnitude < .25f)
|
|
result = result - GetHeight(go.GravityMaterial, go.Shader,
|
|
(Vector2) go.transform.InverseTransformPoint(position.Flatland()) + Vector2.one * .5f);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static Vector2 GetForce(Vector2 position)
|
|
{
|
|
if (Instance.ForceMode == GravityForceMode.Sign)
|
|
{
|
|
var hits = Instance.GravityObjects.Where(go => (go.transform.position.Flatland() - position).sqrMagnitude < go.transform.lossyScale.x)
|
|
.Where(h => !h.CompareTag("IgnoreGravity"));
|
|
|
|
Vector2 force = Vector2.zero;
|
|
foreach (var hit in hits)
|
|
{
|
|
force += (new Vector2(hit.transform.position.x, hit.transform.position.z) - position) *
|
|
GetHeight(hit.GravityMaterial, hit.Shader, hit.transform.InverseTransformPoint(position.Flatland()).Flatland());
|
|
}
|
|
return force * Instance.GlobalGravityMultiplier;
|
|
}
|
|
|
|
var normal = GetNormal(position);
|
|
var f = new Vector2(normal.x, normal.z);
|
|
return f * Instance.GlobalGravityMultiplier * f.sqrMagnitude;// * Mathf.Abs(GetHeight(position));
|
|
}
|
|
|
|
private static float GetHeight(Material mat, string shader, Vector2 textureCoord)
|
|
{
|
|
// var mat = hit.transform.GetComponent<MeshRenderer>().material;
|
|
|
|
switch (shader)
|
|
{
|
|
case "Brushes/Cubic Pulse Brush":
|
|
return mat.GetFloat("_Depth") * CubicPulse(0, .5f, (textureCoord - Vector2.one * .5f).magnitude);
|
|
|
|
case "Brushes/Power Brush":
|
|
return mat.GetFloat("_Depth") * PowerPulse((textureCoord - Vector2.one * .5f).magnitude * 2, mat.GetFloat("_Power"));
|
|
case "Brushes/Radial Wave Brush":
|
|
{
|
|
float dist = (textureCoord - Vector2.one * .5f).magnitude;
|
|
return mat.GetFloat("_Depth") * PowerPulse(dist * 2, mat.GetFloat("_Power")) *
|
|
Mathf.Cos(Mathf.Pow(dist*2, mat.GetFloat("_SinePower")) * mat.GetFloat("_Frequency") + mat.GetFloat("_Phase"));
|
|
}
|
|
case "Brushes/Linear Wave Brush":
|
|
{
|
|
float dist = (textureCoord - Vector2.one * .5f).magnitude;
|
|
return mat.GetFloat("_Depth") * PowerPulse(dist * 2, mat.GetFloat("_Power")) *
|
|
Mathf.Cos((textureCoord.y - .5f) * mat.GetFloat("_Frequency") + mat.GetFloat("_Phase"));
|
|
}
|
|
default:
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public static float CubicPulse(float c, float w, float x)
|
|
{
|
|
x = Mathf.Abs(x - c);
|
|
if (x > w) return 0;
|
|
x /= w;
|
|
return 1.0f - x * x * (3.0f - 2.0f * x);
|
|
}
|
|
|
|
public static float PowerPulse(float x, float pow)
|
|
{
|
|
x = Mathf.Clamp(x, -1, 1);
|
|
return Mathf.Pow((x + 1) * (1 - x), pow);
|
|
}
|
|
|
|
public static Vector3 GetNormal(Vector2 pos, float step, float mul)
|
|
{
|
|
float hL = GetHeight(new Vector2(pos.x - step, pos.y)) * mul;
|
|
float hR = GetHeight(new Vector2(pos.x + step, pos.y)) * mul;
|
|
float hD = GetHeight(new Vector2(pos.x, pos.y - step)) * mul;
|
|
float hU = GetHeight(new Vector2(pos.x, pos.y + step)) * mul;
|
|
|
|
// Deduce terrain normal
|
|
Vector3 normal = new Vector3((hL - hR), (hD - hU), 2);
|
|
normal.Normalize();
|
|
return new Vector3(normal.x, normal.z, normal.y);
|
|
}
|
|
|
|
public static Vector3 GetNormal(Vector2 pos)
|
|
{
|
|
return GetNormal(pos, Instance.GradientStepSize, Instance.NormalMultiplier);
|
|
}
|
|
}
|
|
|
|
public enum GravityForceMode
|
|
{
|
|
Sign,
|
|
Gradient
|
|
}
|