udRenderContext.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using UnityEngine;
  4. namespace udSDK
  5. {
  6. public enum udRenderContextPointMode
  7. {
  8. udRCPM_Rectangles,
  9. udRCPM_Cubes,
  10. udRCPM_Points,
  11. udRCPM_Count
  12. }
  13. public enum udRenderContextFlags
  14. {
  15. udRCF_None = 0, //!< Render the points using the default configuration.
  16. udRCF_PreserveBuffers = 1 << 0, //!< The colour and depth buffers won't be cleared before drawing and existing depth will be respected
  17. udRCF_ComplexIntersections = 1 << 1, //!< This flag is required in some scenes where there is a very large amount of intersecting point clouds
  18. //!< It will internally batch rendering with the udRCF_PreserveBuffers flag after the first render.
  19. udRCF_BlockingStreaming = 1 << 2, //!< This forces the streamer to load as much of the pointcloud as required to give an accurate representation in the current view. A small amount of further refinement may still occur.
  20. udRCF_LogarithmicDepth = 1 << 3, //!< Calculate the depth as a logarithmic distribution.
  21. udRCF_ManualStreamerUpdate = 1 << 4, //!< The streamer won't be updated internally but a render call without this flag or a manual streamer update will be required
  22. udRCF_ZeroAlphaSkip = 1 << 5, //!< If the voxel has 0 alpha (upper 8 bits) after the voxel shader then the voxel will not be drawn to the buffers (effectively skipped)
  23. udRCF_2PixelOpt = 1 << 6, //!< Optimisation that allows the renderer to resolve the last 2 pixels simulataneously, this can result in slight inaccuracies (generally a few pixels) in the final image for a huge performance improvement.
  24. udRCF_DisableOrthographic = 1 << 7, //!< Disables the renderer entering high-performance orthographic mode
  25. }
  26. /*Contains information returned by the picking system
  27. */
  28. [StructLayout(LayoutKind.Sequential)]
  29. unsafe public struct udRenderPicking
  30. {
  31. public UInt32 x;//view space mouse x
  32. public UInt32 y;//view space mouse y
  33. public UInt32 hit;//true if voxel was hit by this pick
  34. public UInt32 isHighestLOD;//true if hit was as accurate as possible
  35. public UInt32 modelIndex; //index of the model in the array hit by this pick
  36. public fixed double pointCenter[3]; //location of the point hit by the pick
  37. public udVoxelID voxelID; //ID of the hit voxel
  38. }
  39. /*Unity serializable equivalent of udRenderPicking
  40. */
  41. public struct udPick
  42. {
  43. public int x; // view space mouse x
  44. public int y; // view space mouse y
  45. public int hit; // true if voxel was hit by this pick
  46. public int isHighestLOD; // true if his was as accurate as possible
  47. public int modelIndex; // the index of the model in the array hit by this pick
  48. public UnityEngine.Vector3 pointCenter; // the position of the point hit by the pick
  49. public udVoxelID voxelID; // ID of the hit voxel
  50. }
  51. [StructLayout(LayoutKind.Sequential)]
  52. public struct udRenderSettings
  53. {
  54. public udRenderContextFlags flags; // optional flags providing information on how to perform the render
  55. public IntPtr pPick;
  56. public udRenderContextPointMode pointMode;
  57. public IntPtr pFilter; // pointer to a udQueryFilter
  58. }
  59. [StructLayout(LayoutKind.Sequential)]
  60. public struct udRenderInstance
  61. {
  62. public IntPtr pointCloud;
  63. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
  64. public double[] worldMatrix;
  65. public IntPtr filter;
  66. public IntPtr voxelShader;
  67. public IntPtr voxelUserData;
  68. }
  69. public class udRenderContext
  70. {
  71. public IntPtr pRenderer = IntPtr.Zero;
  72. private udContext context;
  73. ~udRenderContext()
  74. {
  75. Destroy();
  76. }
  77. public void Create(udContext context)
  78. {
  79. //ensure we destroy the existing context if we are creating a new one:
  80. if (pRenderer != IntPtr.Zero)
  81. Destroy();
  82. if (context.pContext == IntPtr.Zero)
  83. throw new Exception("context not instantiatiated");
  84. udError error = udRenderContext_Create(context.pContext, ref pRenderer);
  85. if (error != udSDK.udError.udE_Success)
  86. throw new Exception("udRenderContext.Create failed: " + error.ToString());
  87. this.context = context;
  88. }
  89. public void Destroy()
  90. {
  91. if (pRenderer == IntPtr.Zero)
  92. {
  93. return;
  94. }
  95. udError error = udRenderContext_Destroy(ref pRenderer);
  96. if (error != udSDK.udError.udE_Success)
  97. throw new Exception("udRenderContext.Destroy failed: " + error.ToString());
  98. pRenderer = IntPtr.Zero;
  99. }
  100. public void Render(udRenderTarget renderView, udRenderInstance[] pModels, int modelCount, RenderOptions options = null )
  101. {
  102. if (modelCount == 0)
  103. return;
  104. if (options == null)
  105. options = new RenderOptions();
  106. if (renderView == null)
  107. throw new Exception("renderView is null");
  108. if (renderView.pRenderView == IntPtr.Zero)
  109. throw new Exception("RenderView not initialised");
  110. if (pRenderer == IntPtr.Zero)
  111. throw new Exception("renderContext not initialised");
  112. udError error = udRenderContext_Render(pRenderer, renderView.pRenderView, pModels, modelCount, options.options);
  113. if (error != udSDK.udError.udE_Success)
  114. {
  115. Debug.Log("udRenderContext.Render failed: " + error.ToString());
  116. }
  117. options.pickRendered = true;
  118. }
  119. [DllImport(UDSDKLibrary.name)]
  120. private static extern udError udRenderContext_Create(IntPtr pContext, ref IntPtr ppRenderer);
  121. [DllImport(UDSDKLibrary.name)]
  122. private static extern udError udRenderContext_Destroy(ref IntPtr ppRenderer);
  123. [DllImport(UDSDKLibrary.name)]
  124. private static extern udError udRenderContext_Render(IntPtr pRenderer, IntPtr pRenderView, udRenderInstance[] pModels, int modelCount, [In, Out] udRenderSettings options);
  125. }
  126. public class RenderOptions
  127. {
  128. // this is an interface to the udRenderSettings struct
  129. // it provides a safe udPick option for accessing the pick results inside unity component scripts
  130. public udRenderSettings options;
  131. public bool pickSet = false;
  132. public bool pickRendered = false;
  133. public udRenderSettings Options {
  134. get
  135. {
  136. return options;
  137. }
  138. }
  139. public RenderOptions(udRenderContextPointMode pointMode, udRenderContextFlags flags)
  140. {
  141. options.pointMode = pointMode;
  142. //this will need to change once support for multiple picks is introduced
  143. options.pPick = Marshal.AllocHGlobal(Marshal.SizeOf<udRenderPicking>());
  144. options.flags = flags;
  145. }
  146. public RenderOptions() : this(udRenderContextPointMode.udRCPM_Rectangles, udRenderContextFlags.udRCF_None)
  147. {
  148. }
  149. ~RenderOptions()
  150. {
  151. Marshal.DestroyStructure<udRenderPicking>(options.pPick);
  152. Marshal.FreeHGlobal(options.pPick);
  153. }
  154. public void setPick(uint x, uint y)
  155. {
  156. udRenderPicking pick = new udRenderPicking();
  157. pick.x = x;
  158. pick.y = y;
  159. Marshal.StructureToPtr(pick, options.pPick, false);
  160. pickRendered = false;
  161. pickSet = true;
  162. }
  163. public udPick getPick()
  164. {
  165. UnityEngine.Debug.Log("Getting pick");
  166. if(!pickSet)
  167. return new udPick();
  168. udRenderPicking targetPick = this.Pick;
  169. udPick newPick = new udPick();
  170. newPick.hit = (int)targetPick.hit;
  171. newPick.x = (int)targetPick.x;
  172. newPick.y = (int)targetPick.y;
  173. unsafe
  174. {
  175. newPick.pointCenter = new UnityEngine.Vector3((float)targetPick.pointCenter[0], (float)targetPick.pointCenter[1], (float)targetPick.pointCenter[2]);
  176. }
  177. newPick.isHighestLOD = (int)targetPick.isHighestLOD;
  178. newPick.voxelID = targetPick.voxelID;
  179. return newPick;
  180. }
  181. public udRenderPicking Pick
  182. {
  183. get
  184. {
  185. if (!pickSet)
  186. return new udRenderPicking();
  187. if (!pickRendered)
  188. throw new Exception("Render must be called before pick can be read");
  189. return (udRenderPicking)Marshal.PtrToStructure(options.pPick, typeof(udRenderPicking));
  190. }
  191. }
  192. }
  193. }