PointCloudRenderer.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Pcx - Point cloud importer & renderer for Unity
  2. // https://github.com/keijiro/Pcx
  3. using UnityEngine;
  4. namespace Pcx
  5. {
  6. /// A renderer class that renders a point cloud contained by PointCloudData.
  7. [ExecuteInEditMode]
  8. public sealed class PointCloudRenderer : MonoBehaviour
  9. {
  10. #region Editable attributes
  11. [SerializeField] PointCloudData _sourceData = null;
  12. public PointCloudData sourceData {
  13. get { return _sourceData; }
  14. set { _sourceData = value; }
  15. }
  16. [SerializeField] Color _pointTint = new Color(0.5f, 0.5f, 0.5f, 1);
  17. public Color pointTint {
  18. get { return _pointTint; }
  19. set { _pointTint = value; }
  20. }
  21. [SerializeField] float _pointSize = 0.05f;
  22. public float pointSize {
  23. get { return _pointSize; }
  24. set { _pointSize = value; }
  25. }
  26. #endregion
  27. #region Public properties (nonserialized)
  28. public ComputeBuffer sourceBuffer { get; set; }
  29. #endregion
  30. #region Internal resources
  31. [SerializeField, HideInInspector] Shader _pointShader = null;
  32. [SerializeField, HideInInspector] Shader _diskShader = null;
  33. #endregion
  34. #region Private objects
  35. Material _pointMaterial;
  36. Material _diskMaterial;
  37. #endregion
  38. #region MonoBehaviour implementation
  39. void OnValidate()
  40. {
  41. _pointSize = Mathf.Max(0, _pointSize);
  42. }
  43. void OnDestroy()
  44. {
  45. if (_pointMaterial != null)
  46. {
  47. if (Application.isPlaying)
  48. {
  49. Destroy(_pointMaterial);
  50. Destroy(_diskMaterial);
  51. }
  52. else
  53. {
  54. DestroyImmediate(_pointMaterial);
  55. DestroyImmediate(_diskMaterial);
  56. }
  57. }
  58. }
  59. void OnRenderObject()
  60. {
  61. // We need a source data or an externally given buffer.
  62. if (_sourceData == null && sourceBuffer == null) return;
  63. // Check the camera condition.
  64. var camera = Camera.current;
  65. if ((camera.cullingMask & (1 << gameObject.layer)) == 0) return;
  66. if (camera.name == "Preview Scene Camera") return;
  67. // TODO: Do view frustum culling here.
  68. // Lazy initialization
  69. if (_pointMaterial == null)
  70. {
  71. _pointMaterial = new Material(_pointShader);
  72. _pointMaterial.hideFlags = HideFlags.DontSave;
  73. _pointMaterial.EnableKeyword("_COMPUTE_BUFFER");
  74. _diskMaterial = new Material(_diskShader);
  75. _diskMaterial.hideFlags = HideFlags.DontSave;
  76. _diskMaterial.EnableKeyword("_COMPUTE_BUFFER");
  77. }
  78. // Use the external buffer if given any.
  79. var pointBuffer = sourceBuffer != null ?
  80. sourceBuffer : _sourceData.computeBuffer;
  81. if (_pointSize == 0)
  82. {
  83. _pointMaterial.SetPass(0);
  84. _pointMaterial.SetColor("_Tint", _pointTint);
  85. _pointMaterial.SetMatrix("_Transform", transform.localToWorldMatrix);
  86. _pointMaterial.SetBuffer("_PointBuffer", pointBuffer);
  87. #if UNITY_2019_1_OR_NEWER
  88. Graphics.DrawProceduralNow(MeshTopology.Points, pointBuffer.count, 1);
  89. #else
  90. Graphics.DrawProcedural(MeshTopology.Points, pointBuffer.count, 1);
  91. #endif
  92. }
  93. else
  94. {
  95. _diskMaterial.SetPass(0);
  96. _diskMaterial.SetColor("_Tint", _pointTint);
  97. _diskMaterial.SetMatrix("_Transform", transform.localToWorldMatrix);
  98. _diskMaterial.SetBuffer("_PointBuffer", pointBuffer);
  99. _diskMaterial.SetFloat("_PointSize", pointSize);
  100. #if UNITY_2019_1_OR_NEWER
  101. Graphics.DrawProceduralNow(MeshTopology.Points, pointBuffer.count, 1);
  102. #else
  103. Graphics.DrawProcedural(MeshTopology.Points, pointBuffer.count, 1);
  104. #endif
  105. }
  106. }
  107. #endregion
  108. }
  109. }