Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLSurfaceGraph.cs @ 9102

Last change on this file since 9102 was 9102, checked in by gkronber, 12 years ago

#1967: ILNumerics source for experimentation

File size: 24.1 KB
Line 
1///
2///    This file is part of ILNumerics Community Edition.
3///
4///    ILNumerics Community Edition - high performance computing for applications.
5///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
6///
7///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
8///    it under the terms of the GNU General Public License version 3 as published by
9///    the Free Software Foundation.
10///
11///    ILNumerics Community Edition is distributed in the hope that it will be useful,
12///    but WITHOUT ANY WARRANTY; without even the implied warranty of
13///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14///    GNU General Public License for more details.
15///
16///    You should have received a copy of the GNU General Public License
17///    along with ILNumerics Community Edition. See the file License.txt in the root
18///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
19///
20///    In addition this software uses the following components and/or licenses:
21///
22///    =================================================================================
23///    The Open Toolkit Library License
24///   
25///    Copyright (c) 2006 - 2009 the Open Toolkit library.
26///   
27///    Permission is hereby granted, free of charge, to any person obtaining a copy
28///    of this software and associated documentation files (the "Software"), to deal
29///    in the Software without restriction, including without limitation the rights to
30///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
31///    the Software, and to permit persons to whom the Software is furnished to do
32///    so, subject to the following conditions:
33///
34///    The above copyright notice and this permission notice shall be included in all
35///    copies or substantial portions of the Software.
36///
37///    =================================================================================
38///   
39
40using System;
41using System.Collections.Generic;
42using System.Text;
43using System.Drawing;
44using System.Data;
45using System.Windows.Forms;
46using ILNumerics.Exceptions;
47using ILNumerics.Drawing;
48using System.Resources;
49using OpenTK;
50using OpenTK.Graphics.OpenGL;
51using OpenTK.Graphics;
52using OpenTK.Graphics.OpenGL.Enums;
53using ILNumerics.Drawing.Graphs;
54using ILNumerics.Drawing.Platform.OpenGL;
55using ILNumerics.Drawing.Misc;
56using ILNumerics.Misc;
57using VERTEXTYPEDEF = ILNumerics.Drawing.Platform.OpenGL.ILOGLSurfaceGraph.VertexC4N3V3;
58
59namespace ILNumerics.Drawing.Platform.OpenGL
60{
61    /// <summary>
62    /// OpenGL implementation for ILSurfaceGraph
63    /// </summary>
64    public class ILOGLSurfaceGraph : ILSurfaceGraph {
65       
66        #region attributes
67        protected float[] m_vertices;
68        protected ShadingStyles m_oldShading;
69        protected ILColormap m_oldColormap;
70        #endregion
71
72
73        #region vertex definition
74        /// <summary>
75        /// Vertex definition: 4Color, 3Normal, 3 Vertex - all float
76        /// </summary>
77        /// <remarks>CAUTION! The vertex is not usable with OpenGL via vartex arrays this way!
78        /// We had to recognize sporadic crashs when drawing this way! Todo: ... to be investigated.</remarks>
79        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
80        public struct VertexC4N3V3 {
81            public float CR;
82            public float CG;
83            public float CB;
84            public float CA;
85            public float Nx;
86            public float Ny;
87            public float Nz;
88            public float Vx;
89            public float Vy;
90            public float Vz;
91        }
92
93        protected override void CreateVertices() {
94            ILColormap colormap = m_panel.Colormap;
95            if (m_vertices == null) {
96                m_vertices = ILMemoryPool.Pool.New<float>(m_Vertcount*10);
97            }
98            float val = 0.0f;
99            float minZ = m_globalClipping.ZMin, minC = (ILMath.isnullorempty(m_colors))? 0.0f : m_colors.MinValue;
100            float maxZ = m_globalClipping.ZMax;
101            bool useColorArray = !(object.Equals(m_colors,null) || m_colors.IsEmpty);
102            float a;
103            if (useColorArray)
104                a = colormap.Length / (m_colors.MaxValue - minC);
105            else {
106                if (maxZ - minZ != 0.0f)
107                    a = colormap.Length / (maxZ - minZ);
108                else
109                    a = 0.0f;
110            }
111            int curVertPos = 0, curVecPos = 0;
112            if (m_shading == ShadingStyles.Interpolate) {
113                #region shading interpolate
114                for (int r = 0; r < m_rows; r++) {
115                    for (int c = 0; c < m_cols; c++) {
116                        curVecPos = r + c * m_rows;
117                        val = m_sourceArray.GetValue(r,c);
118                        // set color values
119                        if (useColorArray)
120                            colormap.Map((m_colors.GetValue(curVecPos) - minC) * a, m_vertices, ref curVertPos);
121                        else {
122                            if (a != 0) {
123                                colormap.Map((val - minZ) * a, m_vertices, ref curVertPos);
124                            } else {
125                                // plane: minz == maxz
126                                colormap.Map(colormap.Length / 2, m_vertices, ref curVertPos);
127                            }
128                        }
129                        m_vertices[curVertPos++] = m_opacity;
130                        curVertPos += 3;
131                        m_vertices[curVertPos++] = m_xCoords[curVecPos];
132                        m_vertices[curVertPos++] = m_yCoords[curVecPos];
133                        m_vertices[curVertPos++] = val;
134                    }
135                }
136                #endregion
137            } else if (m_shading == ShadingStyles.Flat) {
138                #region shading flat
139                /*  Consider a surface area like this:
140                 *
141                 *  8 - 9 -10 -11
142                 *  | / | / | / |
143                 *  4 - 5 - 6 - 7
144                 *  | / | / | / |
145                 *  0 - 1 - 2 - 3
146                 *
147                 *  The rectangle surrounded by 0-1-4-5 is than colored by the
148                 *  vertex 5. This rectangle will be assembled by 2 triangles:
149                 *  0-1-5 and 0-4-5. Therefore the color for both rectangles
150                 *  is the same and must be stored in the vertex No.5.
151                 *  The vertices can be assembled in natural order, beginning
152                 *  with 0 and approching m_vertexCount-1. The color for flat
153                 *  shading is averaged over the neighbor corners of each
154                 *  rectangle. In our Example the color stored in 5 is averaged
155                 *  over the values of the vertices 0,1,4 and 5. The first row
156                 *  and the first column are not used for the surface. However
157                 *  it may _be_ used for the wireframe grid if that is drawn with
158                 *  interpolated colors (Wireframe.Color.IsEmpty). So we must
159                 *  prepare the color for it -> here we just take the value itself.
160                 */
161                // first row: no color average
162                for (int c = 0; c < m_cols; c++) {
163                    val = m_sourceArray.GetValue(0,c);
164                    if (useColorArray)
165                        colormap.Map((m_colors.GetValue(0,c) - minC) * a, m_vertices,ref curVertPos);
166                    else
167                        colormap.Map((val - minZ) * a, m_vertices,ref curVertPos);
168                    m_vertices[curVertPos++] = m_opacity;
169                    curVertPos += 3;
170                    m_vertices[curVertPos++] = m_xCoords[m_rows*c];
171                    m_vertices[curVertPos++] = m_yCoords[m_rows*c];
172                    m_vertices[curVertPos++] = val;
173                }
174                for (int r = 1; r < m_rows; r++) {
175                    val = m_sourceArray.GetValue(r,0);
176                    if (useColorArray)
177                        colormap.Map((m_colors.GetValue(r) - minC) * a, m_vertices,ref curVertPos);
178                    else
179                        colormap.Map((val - minZ) * a, m_vertices,ref curVertPos);
180                    m_vertices[curVertPos++] = m_opacity;
181                    curVertPos += 3;
182                    m_vertices[curVertPos++] = m_xCoords[r];
183                    m_vertices[curVertPos++] = m_yCoords[r];
184                    m_vertices[curVertPos++] = val;
185                    // next columns: average color over precomputed corners
186                    for (int c = 1; c < m_cols; c++) {
187                        curVecPos = r + c * m_rows;
188                        val = m_sourceArray.GetValue(r,c);
189                        val += m_sourceArray.GetValue(r-1,c);
190                        val += m_sourceArray.GetValue(r,c-1);
191                        val += m_sourceArray.GetValue(r-1,c-1);
192                        val /= 4;
193                        if (useColorArray)
194                            colormap.Map((m_colors.GetValue(curVecPos) - minC) * a, m_vertices,ref curVertPos);
195                        else
196                            colormap.Map((val - minZ) * a, m_vertices,ref curVertPos);
197                        m_vertices[curVertPos++] = m_opacity;
198                        curVertPos += 3;
199                        m_vertices[curVertPos++] = m_xCoords[curVecPos];
200                        m_vertices[curVertPos++] = m_yCoords[curVecPos];
201                        m_vertices[curVertPos++] = m_sourceArray.GetValue(r,c);
202                    }
203                }
204                #endregion
205                m_oldColormap = colormap;
206            }
207            #region create normals
208            // todo: depends on lighting enabled or not...!
209            // reset vertices pointer and start all over
210            curVertPos = 0; float nx,ny,nz;
211            for (int r = 0; r < m_rows; r++) {
212                for (int c = 0; c < m_cols; c++) {
213                    nx= m_vertices[curVertPos+7];
214                    ny= m_vertices[curVertPos+8];
215                    nz= m_vertices[curVertPos+9];
216                    if (c > 0) {
217                        nx += m_vertices[curVertPos-3];
218                        ny += m_vertices[curVertPos-2];
219                        nz += m_vertices[curVertPos-1];
220                    }
221                    if (c < m_cols-1) {
222                        nx += m_vertices[curVertPos+17];
223                        ny += m_vertices[curVertPos+18];
224                        nz += m_vertices[curVertPos+19];
225                    }
226                    if (r > 0 && r < m_rows) {
227                        nx += m_vertices[curVertPos-m_cols*10+10];
228                        ny += m_vertices[curVertPos-m_cols*10+11];
229                        nz += m_vertices[curVertPos-m_cols*10+12];
230                    }
231                    if (r < m_rows - 1) {
232                        nx += m_vertices[curVertPos+m_cols*10+10];
233                        ny += m_vertices[curVertPos+m_cols*10+11];
234                        nz += m_vertices[curVertPos+m_cols*10+12];
235                    }
236                    // normalize
237                    float len = (float)Math.Sqrt(nx*nx+ny*ny+nz*nz);
238                    m_vertices[curVertPos+4] = nx / len;
239                    m_vertices[curVertPos+5] = ny / len;
240                    m_vertices[curVertPos+6] = nz / len;
241                    curVertPos+=10;
242                }
243            }
244            #endregion
245            m_oldShading = m_shading;
246            m_vertexReady = true;
247        }
248
249
250        #endregion
251
252        #region constructor
253        internal ILOGLSurfaceGraph(ILOGLPanel panel, ILArray<float> X,
254                                    ILArray<float> Y, ILArray<float> Z, ILArray<float> C,
255                                    ILClippingData clippingContainer)
256                              : base(panel,X,Y,Z,C,clippingContainer) {
257            m_indexReady = false;
258            m_vertexReady = false;
259        }
260
261        #endregion
262
263        #region abstract interface
264        /// <summary>
265        /// Dispose off this graph's vertices
266        /// </summary>
267        public override void Dispose() {
268            base.Dispose();
269            if (m_vertices != null) {
270                ILMemoryPool.Pool.Free<float>(m_vertices);
271            }
272        }
273        /// <summary>
274        /// Draw the graph
275        /// </summary>
276        public override void Draw(ILRenderProperties p) {
277            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
278                          BlendingFactorDest.OneMinusSrcAlpha);           
279            ILLineProperties wireprops = m_wireLines;
280            ILOGLPanel.SetupLineStyle(wireprops);
281            unsafe {
282                fixed (float* pVertices = m_vertices) {
283                    // populate vertex array to GL
284                    GL.InterleavedArrays(InterleavedArrayFormat.C4fN3fV3f
285                                         ,0,(IntPtr)pVertices);
286                    // general setup shading & transparency
287                    if (m_shading == ShadingStyles.Interpolate) {                     
288                        GL.ShadeModel(ShadingModel.Smooth);
289                        //GL.Disable(EnableCap.DepthTest);
290                    } else {
291                        GL.ShadeModel(ShadingModel.Flat);
292                        //if (m_opacity < 1.0f)
293                        //else
294                        //    GL.Enable(EnableCap.DepthTest);
295                    }
296                    GL.Enable(EnableCap.DepthTest);
297                   
298                   
299                    if (m_opacity == 1.0f && m_shading == ShadingStyles.Interpolate) {
300                        #region no transpareny
301                        GL.Disable(EnableCap.Blend);
302                        GL.Enable(EnableCap.DepthTest);
303                        fixed (UInt32* pGridIndices = m_gridIndices)
304                        fixed (UInt32* pIndices = m_indices) {
305                            UInt32* pGridIndWalk = pGridIndices;
306                            // first surface strip
307                            if (m_filled) {
308                                GL.DrawElements(BeginMode.TriangleStrip,m_stripesLen,
309                                                DrawElementsType.UnsignedInt,
310                                                (IntPtr)pIndices);
311                            }   
312                            // first grid strip
313                            if (m_wireLines.Visible) {
314                                if (!wireprops.Color.IsEmpty) {
315                                    // if a color was specified, use it for wireframes!
316                                    GL.DisableClientState(EnableCap.ColorArray);
317                                    //GL.Color3(wireprops.ForeColor); // color for grid lines 
318                                }
319                                GL.DrawElements(BeginMode.Lines,
320                                            m_gridStripsLen + m_gridStripsLenOnce, // 2*(m_cols-1),
321                                            DrawElementsType.UnsignedInt,
322                                            (IntPtr)pGridIndWalk);
323                                pGridIndWalk += (m_gridStripsLen + m_gridStripsLenOnce);
324                                if (!wireprops.Color.IsEmpty) {
325                                    GL.EnableClientState(EnableCap.ColorArray);
326                                }
327                            }
328                            for (int i = 1; i < m_stripesCount; i++) {
329                                // subsequent surface strips
330                                if (m_filled) {
331                                    GL.DrawElements(BeginMode.TriangleStrip,
332                                                    m_stripesLen,
333                                                    DrawElementsType.UnsignedInt,
334                                                    (IntPtr)(pIndices+i*m_stripesLen));
335                                }
336                                // subsequent grid strips
337                                if (m_wireLines.Visible) {
338                                    GL.Disable(EnableCap.Blend);
339                                    if (!wireprops.Color.IsEmpty) {
340                                        // if a color was specified, use it for wireframes!
341                                        GL.DisableClientState(EnableCap.ColorArray);
342                                        //GL.Color3(wireprops.ForeColor); // color for grid lines 
343                                    }
344                                    GL.DrawElements(BeginMode.Lines,
345                                                m_gridStripsLen,
346                                                DrawElementsType.UnsignedInt,
347                                                (IntPtr)(pGridIndWalk));
348                                    pGridIndWalk += m_gridStripsLen;
349                                    if (!wireprops.Color.IsEmpty) {
350                                        GL.EnableClientState(EnableCap.ColorArray);
351                                    }
352                                }
353                            }
354                            GL.Finish();
355                        }
356                        #endregion
357                    } else {
358                        #region transparency or flat shading
359                        GL.Enable(EnableCap.Blend);
360                        fixed (UInt32* pGridIndices = m_gridIndices)
361                        fixed (UInt32* pIndices = m_indices) {
362                            UInt32* pGridIndWalk = pGridIndices;
363                            // first surface strip
364                            if (m_filled) {
365                                GL.DrawElements(BeginMode.Triangles,m_stripesLen,
366                                                DrawElementsType.UnsignedInt,
367                                                (IntPtr)pIndices);
368                            }   
369                            // first grid strip
370                            if (m_wireLines.Visible) {
371                                GL.Disable(EnableCap.Blend);
372                                if (!wireprops.Color.IsEmpty) {
373                                    // if a color was specified, use it for wireframes!
374                                    GL.DisableClientState(EnableCap.ColorArray);
375                                    GL.Color3(m_wireLines.Color);
376                                }
377                                GL.DrawElements(BeginMode.Lines,
378                                            m_gridStripsLen + m_gridStripsLenOnce,
379                                            DrawElementsType.UnsignedInt,
380                                            (IntPtr)pGridIndWalk);
381                                pGridIndWalk += m_gridStripsLen + m_gridStripsLenOnce;
382                                if (!wireprops.Color.IsEmpty) {
383                                    // if a color was specified, use it for wireframes!
384                                    GL.EnableClientState(EnableCap.ColorArray);
385                                }
386                                GL.Enable(EnableCap.Blend);
387                            }
388                            for (int i = 1; i < m_stripesCount; i++) {
389                                // subsequent surface strips
390                                if (m_filled) {
391                                    GL.DrawElements(BeginMode.Triangles,
392                                                    m_stripesLen,
393                                                    DrawElementsType.UnsignedInt,
394                                                    (IntPtr)(pIndices+i*m_stripesLen));
395                                }
396                                // subsequent grid strips
397                                if (m_wireLines.Visible) {
398                                    GL.Disable(EnableCap.Blend);
399                                    if (!wireprops.Color.IsEmpty) {
400                                        // if a color was specified, use it for wireframes!
401                                        GL.DisableClientState(EnableCap.ColorArray);
402                                        GL.Color3(m_wireLines.Color);
403                                    }
404                                    GL.DrawElements(BeginMode.Lines,
405                                                m_gridStripsLen,
406                                                DrawElementsType.UnsignedInt,
407                                                (IntPtr)(pGridIndWalk));
408                                    if (!wireprops.Color.IsEmpty) {
409                                        GL.EnableClientState(EnableCap.ColorArray);
410                                    }
411                                    GL.Enable(EnableCap.Blend);
412                                    pGridIndWalk += m_gridStripsLen;
413                                }
414                            }
415                            GL.Finish();
416                        }
417                        #endregion
418                    }
419                }
420            }
421            //GL.Disable(EnableCap.Lighting);
422            //GL.PopMatrix();
423        }
424        /// <summary>
425        /// Ensures the recreation of the graph if neccessary
426        /// </summary>
427        public override void Invalidate() {
428            if (m_panel == null) return;
429            if (Math.Floor(m_panel.Camera.Phi / (Math.PI / 4.0)) != m_oldSubQuadrant) {   
430                //must only recalculate indices, and only if the camera subquadrant has changed
431                m_indexReady = false;
432                m_isReady = false;
433            }
434            if (m_oldShading != m_shading) {
435                m_indexReady = false;
436                m_vertexReady = false;
437                m_isReady = false;
438            }
439            if (m_oldColormap != m_panel.Colormap) {
440                m_vertexReady = false;
441                m_isReady = false;
442            }
443        }
444        public override void DrawToLegend(ILRenderProperties p, Rectangle sampleRect, Rectangle labelRect) {
445            if (m_filled) {
446                // draw inner filled area
447                GL.ShadeModel(ShadingModel.Smooth);
448                GL.Begin(BeginMode.TriangleStrip);
449                    GL.Color3(m_panel.Colormap[m_panel.Colormap.Length-1]);
450                    GL.Vertex2(sampleRect.X,sampleRect.Y + sampleRect.Height);
451                    GL.Color3(m_panel.Colormap[(int)(m_panel.Colormap.Length/2)]);
452                    GL.Vertex2(sampleRect.X,sampleRect.Y);
453                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y + sampleRect.Height);
454                    GL.Color3(m_panel.Colormap[0]);
455                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y);
456                GL.End();
457            }
458            if (m_wireLines.Visible) {
459                ILNumerics.Drawing.Platform.OpenGL.ILOGLPanel.SetupLineStyle(m_wireLines);
460                GL.Begin(BeginMode.LineStrip);
461                    GL.Vertex2(sampleRect.X,sampleRect.Y);
462                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y);
463                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y + sampleRect.Height);
464                    GL.Vertex2(sampleRect.X,sampleRect.Y + sampleRect.Height);
465                    GL.Vertex2(sampleRect.X,sampleRect.Y);
466                GL.End();
467            }
468            m_label.m_position.X = labelRect.X + labelRect.Width / 2;
469            m_label.m_position.Y = labelRect.Y + labelRect.Height / 2;
470            m_label.Anchor = new PointF(.5f,0);  //  = TickLabelAlign.center | TickLabelAlign.vertCenter;
471            m_label.Draw(p);
472        }
473        #endregion
474
475        #region helper function
476
477        protected override void m_globalClipping_Changed(object sender, ClippingChangedEventArgs e) {
478            base.m_globalClipping_Changed(sender, e);
479            m_vertexReady = false;
480            m_indexReady = false;
481            Configure();
482        }
483       
484        #endregion
485    }
486}
Note: See TracBrowser for help on using the repository browser.