Question by
doug-in-a-box · Dec 17, 2016 at 03:54 AM ·
unity 5colider
how to make this Deformable Surface collidable with wheel colider
Hey all, I recently got this asset from the store "Deformable Surface" but my cars wheel colliders go straight through it like its not even there. I was wondering if there's a way to make it have a kind of resitece. or something similar? thanks all in advance.
the Deformable Surface script:
using UnityEngine; using DeformableSurfaceExtensions;
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider))] public class DeformableSurface : MonoBehaviour { #region Const public const string VERSION = "1.0";
public const int GROUP_THREADS_COUNT = 8;
public const int GEN_NORMAL_KERNEL_ID = 0;
public const int DEFORM_KERNEL_ID = 1;
public const int BLUR_H_KERNEL_ID = 2;
public const int BLUR_V_KERNEL_ID = 3;
public const int DEPTH_TO_BLUR_KERNEL_ID = 4;
public const int GET_OFFSET_KERNEL_ID = 6;
public static float[][] BLUR_WEIGHTS =
{
new[] { 0.44198f, 0.27901f, 0, 0, 0, 0, 0 },
new[] { 0.38774f, 0.24477f, 0.06136f, 0, 0, 0, 0 },
new[] { 0.383103f, 0.241843f, 0.060626f, 0.00598f, 0, 0, 0 },
new[] { 0.382928f, 0.241732f, 0.060598f, 0.005977f, 0.000229f, 0, 0 },
new[] { 0.382925f, 0.24173f, 0.060598f, 0.005977f, 0.000229f, 0.000003f, 0 },
new[] { 0.382925f, 0.24173f, 0.060598f, 0.005977f, 0.000229f, 0.000003f, 0 }
};
private static Texture2D BlurWeights;
#endregion
#region Properties
public SurfaceData Data
{
get { return _data; }
set
{
if (value == null)
return;
MeshFilter.sharedMesh = value.MeshBase;
MeshRenderer.sharedMaterial = value.SourceMaterial;
MeshCollider.sharedMesh = value.MeshCollider;
_data = value;
}
}
[SerializeField]
private SurfaceData _data;
/// <summary>
/// Returns true if there are more than one <see cref="DeformableSurface"/> on the scene.
/// It means that all data forced to be passed to compute shader each frame for each instance
/// </summary>
public bool IsInstance { get; set; }
/// <summary>
/// Enables or disables deformation
/// </summary>
public bool DeformEnabled
{
get { return _deformEnabled; }
set
{
if (_depthCamera != null)
_depthCamera.enabled = value;
_deformEnabled = value;
}
}
[SerializeField]
private bool _deformEnabled = true;
public MeshFilter MeshFilter { get { return GetComponent<MeshFilter>(); } }
public MeshRenderer MeshRenderer { get { return GetComponent<MeshRenderer>(); } }
public MeshCollider MeshCollider { get { return GetComponent<MeshCollider>(); } }
//Process
/// <summary>
/// All objects which may deform the surface are passed to this texture as depth value.
/// You may draw something to this texture and then call <see cref="Deform"/> for manual deformation
/// </summary>
public RenderTexture DepthRt { get; private set; }
public RenderTexture BlurTempRt { get; private set; }
public RenderTexture DeformRt { get; private set; }
public RenderTexture NormalRt { get; private set; }
#endregion
private Camera _depthCamera;
private MaterialPropertyBlock _matPropertyBlock;
private int _threadGroupsX;
private int _threadGroupsY;
void Awake()
{
Init();
}
void Init()
{
_matPropertyBlock = new MaterialPropertyBlock();
DeformRt = GetNewRt("DeformRT", RenderTextureFormat.RFloat, FilterMode.Bilinear, true);
Graphics.Blit(Data.OffsetMap, DeformRt);
_matPropertyBlock.SetTexture(SurfaceData.SHADER_MAPS_TEX_NAMES[1], DeformRt);
NormalRt = GetNewRt("NormalRT", RenderTextureFormat.Default, FilterMode.Bilinear, true);
Graphics.Blit(Data.NormalMap, NormalRt);
_matPropertyBlock.SetTexture(SurfaceData.SHADER_MAPS_TEX_NAMES[2], NormalRt);
MeshRenderer.SetPropertyBlock(_matPropertyBlock);
InitBlurWeights();
InitDepthCamera();
if (Data.Smoothing)
BlurTempRt = GetNewRt("BlurTempRT", RenderTextureFormat.RFloat, FilterMode.Point, true);
InitCompute();
_threadGroupsX = Data.HeightMap.width / GROUP_THREADS_COUNT;
_threadGroupsY = Data.HeightMap.height / GROUP_THREADS_COUNT;
DeformableSurface[] instances = FindObjectsOfType<DeformableSurface>();
if (instances.Length > 1)
IsInstance = true;
for (int i = 0; i < instances.Length; i++)
if (instances[i] != this)
instances[i].IsInstance = true;
}
void InitBlurWeights()
{
if (BlurWeights != null)
return;
BlurWeights = new Texture2D(7, 6, TextureFormat.RFloat, false)
{
name = "BlurWeights",
filterMode = FilterMode.Point,
wrapMode = TextureWrapMode.Clamp
};
for (int i = 0; i < BlurWeights.height; i++)
for (int j = 0; j < BlurWeights.width; j++)
BlurWeights.SetPixel(j, i, new Color(BLUR_WEIGHTS[i][j], 0, 0, 0));
BlurWeights.Apply();
Data.SurfaceKernels.SetTexture(BLUR_H_KERNEL_ID, "BlurWeights", BlurWeights);
Data.SurfaceKernels.SetTexture(BLUR_V_KERNEL_ID, "BlurWeights", BlurWeights);
}
void InitDepthCamera()
{
_depthCamera = new GameObject("RtCamera").AddComponent<Camera>();
_depthCamera.gameObject.hideFlags = HideFlags.HideInHierarchy;
_depthCamera.transform.parent = transform;
_depthCamera.transform.localPosition = new Vector3(Data.MeshWidth / 2f, 0, Data.MeshLength / 2f) * Data.MeshScale;
_depthCamera.transform.rotation = Quaternion.Euler(-90, 0, 0);
_depthCamera.clearFlags = CameraClearFlags.Depth;
_depthCamera.cullingMask = Data.CollisionMask;
_depthCamera.orthographic = true;
_depthCamera.orthographicSize = (Data.MeshLength / 2f) * Data.MeshScale;
_depthCamera.nearClipPlane = 0;
_depthCamera.farClipPlane = Data.MaxHeightValue + Data.MaxOffsetValue;
_depthCamera.depthTextureMode = DepthTextureMode.Depth;
_depthCamera.renderingPath = RenderingPath.VertexLit;
DepthRt = GetNewRt("DepthRT", RenderTextureFormat.RFloat, FilterMode.Bilinear, true);
_depthCamera.targetTexture = DepthRt;
_depthCamera.gameObject.AddComponent<DepthCamera>().Init(this);
if (!DeformEnabled)
_depthCamera.enabled = false;
}
void InitCompute()
{
Data.SurfaceKernels.SetFloat("MaxHeightValue", Data.MaxHeightValue);
Data.SurfaceKernels.SetFloat("MaxOffsetValue", Data.MaxOffsetValue);
Data.SurfaceKernels.SetFloat("TotalMaxValue", Data.MaxHeightValue + Data.MaxOffsetValue);
Data.SurfaceKernels.SetFloat("DeformSpeed", Data.DeformSpeed);
Data.SurfaceKernels.SetTexture(DEFORM_KERNEL_ID, "HeightMap", Data.HeightMap);
Data.SurfaceKernels.SetTexture(DEFORM_KERNEL_ID, "DepthRT", DepthRt);
Data.SurfaceKernels.SetTexture(DEFORM_KERNEL_ID, "DeformRT", DeformRt);
Data.SurfaceKernels.SetTexture(DEFORM_KERNEL_ID, "NormalRT", NormalRt);
if (!Data.Smoothing)
return;
Data.SurfaceKernels.SetInt("BlurRadius", Data.SmoothingRadius + 2);
Data.SurfaceKernels.SetInt("BlurIndex", Data.SmoothingRadius);
Data.SurfaceKernels.SetTexture(DEPTH_TO_BLUR_KERNEL_ID, "DepthRT", DepthRt);
Data.SurfaceKernels.SetTexture(DEPTH_TO_BLUR_KERNEL_ID, "BlurTempRT", BlurTempRt);
Data.SurfaceKernels.SetTexture(BLUR_H_KERNEL_ID, "BlurTempRT", BlurTempRt);
Data.SurfaceKernels.SetTexture(BLUR_V_KERNEL_ID, "BlurTempRT", BlurTempRt);
Data.SurfaceKernels.SetTexture(BLUR_H_KERNEL_ID, "DepthRT", DepthRt);
Data.SurfaceKernels.SetTexture(BLUR_V_KERNEL_ID, "DepthRT", DepthRt);
}
RenderTexture GetNewRt(string rtName, RenderTextureFormat format, FilterMode filter, bool rndWrite)
{
RenderTexture rt = new RenderTexture(Data.HeightMap.width, Data.HeightMap.height, 0, format)
{
name = rtName,
wrapMode = TextureWrapMode.Clamp,
autoGenerateMips = false,
enableRandomWrite = rndWrite,
filterMode = filter
};
rt.Create();
return rt;
}
/// <summary>
/// Manually applies deformation to the surface. This function automatically invoked by depth camera every frame
/// </summary>
public void Deform()
{
if (!DeformEnabled)
return;
if (IsInstance)
InitCompute();
if (Data.Smoothing && BlurTempRt)
{
Data.SurfaceKernels.Dispatch(4, _threadGroupsX, _threadGroupsY, 1);
for (int i = 0; i < Data.SmoothingPasses; i++)
{
Data.SurfaceKernels.Dispatch(BLUR_H_KERNEL_ID, _threadGroupsX, _threadGroupsY, 1);
Data.SurfaceKernels.Dispatch(BLUR_V_KERNEL_ID, _threadGroupsX, _threadGroupsY, 1);
}
}
Data.SurfaceKernels.Dispatch(DEFORM_KERNEL_ID, _threadGroupsX, _threadGroupsY, 1);
}
/// <summary>
/// Removes all changes done in deformable part and restores initial state of the surface
/// </summary>
public void Restore()
{
Graphics.Blit(Data.OffsetMap, DeformRt);
}
/// <summary>
/// Returns offset value at given point. Returns -1 if the point is out of surface offset bounds
/// </summary>
/// <param name="point">Position in world space</param>
/// <returns></returns>
public float GetCollisionOffset(Vector3 point)
{
OffsetValue[] ovData = new OffsetValue[1];
Vector3 localPos = point - transform.position;
Vector3 boundsSize = MeshFilter.sharedMesh.bounds.size;
#region Check bounds
bool xCheck = localPos.x < 0 || localPos.x > boundsSize.x;
bool yCheck = localPos.y < 0 || localPos.y > boundsSize.y;
bool zCheck = localPos.z < 0 || localPos.z > boundsSize.z;
if (xCheck || yCheck || zCheck)
return -1;
#endregion
Vector3 mapPos = new Vector3(
(localPos.x / boundsSize.x) * Data.HeightMap.width,
localPos.y,
(localPos.z / boundsSize.z) * Data.HeightMap.height);
ovData[0].InPos = mapPos;
#region Compute
ComputeBuffer buffer = new ComputeBuffer(1, 16);
buffer.SetData(ovData);
Data.SurfaceKernels.SetTexture(GET_OFFSET_KERNEL_ID, "HeightMap", Data.HeightMap);
Data.SurfaceKernels.SetTexture(GET_OFFSET_KERNEL_ID, "DeformRT", DeformRt);
Data.SurfaceKernels.SetBuffer(GET_OFFSET_KERNEL_ID, "OutOffset", buffer);
Data.SurfaceKernels.Dispatch(GET_OFFSET_KERNEL_ID, 1, 1, 1);
buffer.GetData(ovData);
buffer.Release();
#endregion
return ovData[0].OutValue;
}
/// <summary>
/// Returns offset values at given points. Use this function instead of <see cref="GetCollisionOffset"/> for the large amount of points. 1024 points maximum
/// </summary>
/// <param name="points">Positions in world space</param>
/// <returns></returns>
public float[] GetCollisionsOffset(Vector3[] points)
{
if (points.Length > 1024)
return null;
OffsetValue[] ovData = new OffsetValue[points.Length];
Vector3 boundsSize = MeshFilter.sharedMesh.bounds.size;
#region Calculate InPos
for (int i = 0; i < ovData.Length; i++)
{
Vector3 localPos = points[i] - transform.position;
Vector3 mapPos = new Vector3(
(localPos.x / boundsSize.x) * Data.HeightMap.width,
localPos.y,
(localPos.z / boundsSize.z) * Data.HeightMap.height);
ovData[i].InPos = mapPos;
}
#endregion
#region Compute
ComputeBuffer buffer = new ComputeBuffer(ovData.Length, OffsetValue.STRUCT_SIZE);
buffer.SetData(ovData);
Data.SurfaceKernels.SetTexture(GET_OFFSET_KERNEL_ID, "HeightMap", Data.HeightMap);
Data.SurfaceKernels.SetTexture(GET_OFFSET_KERNEL_ID, "DeformRT", DeformRt);
Data.SurfaceKernels.SetBuffer(GET_OFFSET_KERNEL_ID, "OutOffset", buffer);
Data.SurfaceKernels.Dispatch(GET_OFFSET_KERNEL_ID, ovData.Length, 1, 1);
buffer.GetData(ovData);
buffer.Release();
#endregion
#region Check bounds
for (int i = 0; i < ovData.Length; i++)
{
Vector3 localPos = points[i] - transform.position;
bool xCheck = localPos.x < 0 || localPos.x > boundsSize.x;
bool yCheck = localPos.y < 0 || localPos.y > boundsSize.y;
bool zCheck = localPos.z < 0 || localPos.z > boundsSize.z;
if (xCheck || yCheck || zCheck)
ovData[i].OutValue = -1;
}
#endregion
float[] offsetValues = new float[ovData.Length];
for (int i = 0; i < offsetValues.Length; i++)
offsetValues[i] = ovData[i].OutValue;
return offsetValues;
}
struct OffsetValue
{
public const int STRUCT_SIZE = 16;
public Vector3 InPos;
public float OutValue;
}
}
Comment
Your answer
Follow this Question
Related Questions
change unity hub location 0 Answers
Issue opening unity 1 Answer
inputH/inputV Does not exist 1 Answer
How can check if an game object is garbed in Unity VR oculus integration 0 Answers