4eb26351ef1e8aa4232eb39a11f00d53fa3e24dd
[occt.git] / samples / CSharp / WPF_D3D / D3DViewer.cs
1 using System;
2 using System.Windows;
3 using System.Windows.Media;
4 using System.Windows.Interop;
5 using System.Runtime.InteropServices;
6
7 namespace IE_WPF_D3D
8 {
9   /// <summary>
10   /// Tool object for output OCCT rendering with Direct3D.
11   /// </summary>
12   class D3DViewer
13   {
14     /// <summary> Direct3D renderer. </summary>
15     private IntPtr myD3DRender;
16
17     /// <summary> Direct3D output image. </summary>
18     private D3DImage myD3DImage = new D3DImage ();
19
20     /// <summary> Direct3D color surface. </summary>
21     private IntPtr myColorSurf;
22
23     public OCCViewer Viewer;
24
25     /// <summary> Creates new Direct3D-based OCCT viewer. </summary>
26     public D3DViewer ()
27     {
28       myD3DImage.IsFrontBufferAvailableChanged
29         += new DependencyPropertyChangedEventHandler (OnIsFrontBufferAvailableChanged);
30
31       BeginRenderingScene ();
32     }
33
34     /// <summary> Creates new Direct3D-based OCCT viewer. </summary>
35     private void OnIsFrontBufferAvailableChanged (object sender, DependencyPropertyChangedEventArgs e)
36     {
37       // If the front buffer is available, then WPF has just created a new
38       // Direct3D device, thus we need to start rendering our custom scene
39       if (myD3DImage.IsFrontBufferAvailable)
40       {
41         BeginRenderingScene ();
42       }
43       else
44       {
45         // If the front buffer is no longer available, then WPF has lost Direct3D
46         // device, thus we need to stop rendering until the new device is created
47         StopRenderingScene ();
48       }
49     }
50
51     private bool myIsFailed = false;
52
53     /// <summary> Initializes Direct3D-OCCT rendering. </summary>
54     private void BeginRenderingScene ()
55     {
56       if (myIsFailed)
57       {
58         return;
59       }
60
61       if (myD3DImage.IsFrontBufferAvailable)
62       {
63         IntPtr aWinHandle;
64         IntPtr aD3DDevice;
65
66         // Initialize Direct3D device and render target
67         myD3DRender = Direct3DProxy.InitRender(out aWinHandle, out aD3DDevice);
68
69         Viewer = new OCCViewer();
70
71         if (!Viewer.InitInterop (aWinHandle, aD3DDevice))
72         {
73           MessageBox.Show ("Failed to initialize OpenGL-Direct3D interoperability!",
74             "Error", MessageBoxButton.OK, MessageBoxImage.Error);
75
76           myIsFailed = true;
77
78           if (myD3DRender != IntPtr.Zero)
79               Direct3DProxy.ReleaseRender(ref myD3DRender);
80
81           return;
82         }
83
84         // Leverage the Rendering event of WPF composition
85         // target to update the our custom Direct3D scene
86         CompositionTarget.Rendering += OnRendering;
87       }
88     }
89
90     /// <summary> Initializes Direct3D-OCCT rendering. </summary>
91     public void StopRenderingScene ()
92     {
93       // This method is called when WPF loses its Direct3D device,
94       // so we should just release our custom Direct3D scene
95       CompositionTarget.Rendering -= OnRendering;
96
97       if (myD3DRender != IntPtr.Zero)
98           Direct3DProxy.ReleaseRender(ref myD3DRender);
99
100       myColorSurf = IntPtr.Zero;
101     }
102
103     /// <summary> Initializes Direct3D-OCCT rendering. </summary>
104     private void OnRendering (object sender, EventArgs e)
105     {
106       UpdateScene ();
107     }
108
109     /// <summary> Current size of rendering window. </summary>
110     private WndSize mySize = new WndSize(1, 1);
111
112     /// <summary> Initializes Direct3D-OCCT rendering. </summary>
113     private void UpdateScene ()
114     {
115       if (!myIsFailed && myD3DImage.IsFrontBufferAvailable && myColorSurf != IntPtr.Zero)
116       {
117         myD3DImage.Lock ();
118         {
119           // Update the scene (via a call into our custom library)
120           Viewer.View.RedrawView ();
121
122           // Invalidate the updated region of the D3DImage
123           myD3DImage.AddDirtyRect(new Int32Rect(0, 0, mySize.cx, mySize.cy));
124         }
125         myD3DImage.Unlock ();
126       }
127     }
128
129     /// <summary> Resizes Direct3D surfaces and OpenGL FBO. </summary>
130     public void Resize (int theSizeX, int theSizeY)
131     {
132         mySize = new WndSize(theSizeX, theSizeY);
133
134       if (!myIsFailed && myD3DImage.IsFrontBufferAvailable)
135       {
136         IntPtr aColorSurfShare;
137
138         // Initialize Direct3D device and render target
139         Direct3DProxy.ResizeWindow(ref myD3DRender, ref mySize, out myColorSurf, out aColorSurfShare);
140
141         // Set the back buffer for Direct3D WPF image
142         myD3DImage.Lock ();
143         {
144           myD3DImage.SetBackBuffer (D3DResourceType.IDirect3DSurface9, myColorSurf);
145         }
146         myD3DImage.Unlock ();
147
148         Viewer.View.ResizeBridgeFBO(mySize.cx, mySize.cy, myColorSurf, aColorSurfShare);
149       }
150     }
151
152     public D3DImage Image
153     {
154       get
155       {
156         return myD3DImage;
157       }
158     }
159   }
160 }