Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include <GL/glew.h>
11 : #include <vector>
12 : #include "OpenGLRender.hxx"
13 : #include <vcl/bmpacc.hxx>
14 : #include <vcl/graph.hxx>
15 : #include <com/sun/star/awt/XBitmap.hpp>
16 : #include <com/sun/star/beans/XPropertySet.hpp>
17 : #include <com/sun/star/graphic/XGraphic.hpp>
18 : #include <comphelper/InlineContainer.hxx>
19 : #include <com/sun/star/beans/XPropertySet.hpp>
20 : #include <com/sun/star/drawing/CircleKind.hpp>
21 : #include <com/sun/star/drawing/DoubleSequence.hpp>
22 : #include <com/sun/star/drawing/FlagSequence.hpp>
23 : #include <com/sun/star/drawing/FillStyle.hpp>
24 : #include <com/sun/star/drawing/LineStyle.hpp>
25 : #include <com/sun/star/drawing/NormalsKind.hpp>
26 : #include <com/sun/star/drawing/PointSequence.hpp>
27 : #include <com/sun/star/drawing/PolygonKind.hpp>
28 : #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
29 : #include <com/sun/star/drawing/ProjectionMode.hpp>
30 : #include <com/sun/star/drawing/ShadeMode.hpp>
31 : #include <com/sun/star/drawing/TextFitToSizeType.hpp>
32 : #include <com/sun/star/drawing/TextureProjectionMode.hpp>
33 : #include <com/sun/star/text/XText.hpp>
34 : #include <com/sun/star/uno/Any.hxx>
35 : #include <vcl/virdev.hxx>
36 : #include <vcl/dibtools.hxx>
37 :
38 : #include <osl/file.hxx>
39 : #include <rtl/bootstrap.hxx>
40 : #include <config_folders.h>
41 :
42 : #include <boost/scoped_array.hpp>
43 :
44 : using namespace com::sun::star;
45 :
46 : using namespace std;
47 :
48 : #define DEBUG_PNG 0
49 : #if RENDER_TO_FILE
50 : #define BMP_HEADER_LEN 54
51 : #endif
52 :
53 : #if DEBUG_PNG
54 : #include <vcl/pngwrite.hxx>
55 : #endif
56 :
57 : #define GL_PI 3.14159f
58 :
59 : #if defined( _WIN32 )
60 : #define WGL_SAMPLE_BUFFERS_ARB 0x2041
61 : #define WGL_SAMPLES_ARB 0x2042
62 : #endif
63 :
64 : #define Z_STEP 0.001f
65 :
66 0 : int static checkGLError(const char *file, int line)
67 : {
68 : GLenum glErr;
69 0 : int retCode = 0;
70 0 : glErr = glGetError();
71 0 : while (glErr != GL_NO_ERROR)
72 : {
73 0 : const GLubyte* sError = gluErrorString(glErr);
74 :
75 0 : if (sError)
76 : SAL_WARN("chart2.opengl", "GL Error #" << glErr << "(" << gluErrorString(glErr) << ") " << " in File " << file << " at line: " << line);
77 : else
78 : SAL_WARN("chart2.opengl", "GL Error #" << glErr << " (no message available)" << " in File " << file << " at line: " << line);
79 :
80 0 : retCode = -1;
81 0 : return retCode;
82 : }
83 0 : return retCode;
84 : }
85 :
86 : static bool bGlewInit = false;
87 :
88 : #define CHECK_GL_ERROR() checkGLError(__FILE__, __LINE__)
89 :
90 : #define CHECK_GL_FRAME_BUFFER_STATUS() \
91 : status = glCheckFramebufferStatus(GL_FRAMEBUFFER);\
92 : if( status != GL_FRAMEBUFFER_COMPLETE ) {\
93 : SAL_WARN("chart2.opengl", "OpenGL error: " << status );\
94 : return -1;\
95 : }
96 :
97 : namespace {
98 :
99 0 : OUString getShaderFolder()
100 : {
101 0 : OUString aUrl("$BRAND_BASE_DIR/" LIBO_ETC_FOLDER);
102 0 : rtl::Bootstrap::expandMacros(aUrl);
103 :
104 0 : return aUrl + "/opengl/";
105 : }
106 :
107 0 : OUString maShaderFolder = getShaderFolder();
108 :
109 0 : OString loadShader(const OUString& rFilename)
110 : {
111 0 : OUString aFileURL = maShaderFolder + rFilename +".glsl";
112 0 : osl::File aFile(aFileURL);
113 0 : if(aFile.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None)
114 : {
115 0 : sal_uInt64 nSize = 0;
116 0 : aFile.getSize(nSize);
117 0 : char* content = new char[nSize+1];
118 0 : sal_uInt64 nBytesRead = 0;
119 0 : aFile.read(content, nSize, nBytesRead);
120 0 : if(nSize != nBytesRead)
121 : assert(false);
122 :
123 0 : content[nSize] = 0;
124 0 : return OString(content);
125 : }
126 : else
127 : {
128 : SAL_WARN("chart2.opengl", "could not load the file: " << aFileURL);
129 : }
130 :
131 0 : return OString();
132 : }
133 :
134 : }
135 :
136 0 : GLint OpenGLRender::LoadShaders(const OUString& rVertexShaderName,const OUString& rFragmentShaderName)
137 : {
138 : // Create the shaders
139 0 : GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
140 0 : GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
141 :
142 0 : GLint Result = GL_FALSE;
143 : int InfoLogLength;
144 :
145 : // Compile Vertex Shader
146 0 : OString aVertexShaderSource = loadShader(rVertexShaderName);
147 0 : char const * VertexSourcePointer = aVertexShaderSource.getStr();
148 0 : glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
149 0 : glCompileShader(VertexShaderID);
150 :
151 : // Check Vertex Shader
152 0 : glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
153 0 : if ( !Result )
154 : {
155 0 : glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
156 0 : if ( InfoLogLength > 0 )
157 : {
158 0 : std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
159 0 : glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
160 0 : VertexShaderErrorMessage.push_back('\0');
161 0 : SAL_WARN("chart2.opengl", "vertex shader compile failed : " << &VertexShaderErrorMessage[0]);
162 : }
163 : else
164 : SAL_WARN("chart2.opengl", "vertex shader compile failed without error log");
165 :
166 0 : return 0;
167 : }
168 :
169 : // Compile Fragment Shader
170 0 : OString aFragmentShaderSource = loadShader(rFragmentShaderName);
171 0 : char const * FragmentSourcePointer = aFragmentShaderSource.getStr();
172 0 : glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
173 0 : glCompileShader(FragmentShaderID);
174 :
175 : // Check Fragment Shader
176 0 : glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
177 0 : if ( !Result )
178 : {
179 0 : glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
180 0 : if ( InfoLogLength > 0 )
181 : {
182 0 : std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
183 0 : glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
184 0 : FragmentShaderErrorMessage.push_back('\0');
185 0 : SAL_WARN("chart2.opengl", "fragment shader compile failed : " << &FragmentShaderErrorMessage[0]);
186 : }
187 : else
188 : SAL_WARN("chart2.opengl", "fragment shader compile failed without error log");
189 :
190 :
191 0 : return 0;
192 : }
193 :
194 : // Link the program
195 0 : GLint ProgramID = glCreateProgram();
196 0 : glAttachShader(ProgramID, VertexShaderID);
197 0 : glAttachShader(ProgramID, FragmentShaderID);
198 0 : glLinkProgram(ProgramID);
199 :
200 : // Check the program
201 0 : glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
202 0 : if ( !Result )
203 : {
204 0 : glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
205 0 : if ( InfoLogLength > 0 )
206 : {
207 0 : std::vector<char> ProgramErrorMessage(InfoLogLength+1);
208 0 : glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
209 0 : ProgramErrorMessage.push_back('\0');
210 0 : SAL_WARN("chart2.opengl", "Shader Program failed : " << &ProgramErrorMessage[0]);
211 : }
212 : else
213 : SAL_WARN("chart2.opengl", "shader program link failed without error log");
214 :
215 0 : return 0;
216 : }
217 :
218 0 : glDeleteShader(VertexShaderID);
219 0 : glDeleteShader(FragmentShaderID);
220 :
221 0 : return ProgramID;
222 : }
223 :
224 : namespace {
225 :
226 : GLfloat texCoords[] = {
227 : 0.0f, 0.0f,
228 : 1.0f, 0.0f,
229 : 1.0f, 1.0f,
230 : 0.0f, 1.0f
231 : };
232 :
233 : }
234 :
235 0 : int OpenGLRender::InitOpenGL()
236 : {
237 : //TODO: moggi: get the information from the context
238 0 : mbArbMultisampleSupported = true;
239 0 : if(!bGlewInit)
240 : {
241 0 : glewExperimental = GL_TRUE;
242 0 : if (glewInit() != GLEW_OK)
243 : {
244 : SAL_WARN("chart2.opengl", "Failed to initialize GLEW");
245 0 : return -1;
246 : }
247 : else
248 0 : bGlewInit = true;
249 : }
250 :
251 : // These guys don't just check support but setup the vtables.
252 0 : if (glewIsSupported("framebuffer_object") != GLEW_OK)
253 : {
254 : SAL_WARN("chart2.opengl", "GL stack has no framebuffer support");
255 0 : return -1;
256 : }
257 :
258 0 : glEnable(GL_TEXTURE_2D);
259 0 : glEnable(GL_CULL_FACE);
260 0 : glCullFace(GL_BACK);
261 0 : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
262 : // Enable depth test
263 0 : glEnable(GL_DEPTH_TEST);
264 : // Accept fragment if it closer to the camera than the former one
265 0 : glDepthFunc(GL_LESS);
266 0 : glEnable(GL_POINT_SMOOTH);
267 0 : glEnable(GL_LINE_SMOOTH);
268 0 : glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
269 0 : glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
270 0 : glEnable(GL_BLEND);
271 0 : glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
272 :
273 0 : glClearColor (1.0, 1.0, 1.0, 1.0);
274 0 : glClear(GL_COLOR_BUFFER_BIT);
275 0 : glClearDepth(1.0f);
276 0 : glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
277 :
278 : //Init the Projection matrix
279 0 : m_Projection = glm::ortho(0.f, float(m_iWidth), 0.f, float(m_iHeight), -1.f, 1.f);
280 0 : m_View = glm::lookAt(glm::vec3(0,0,1), // Camera is at (4,3,-3), in World Space
281 : glm::vec3(0,0,0), // and looks at the origin
282 : glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down)
283 0 : );
284 0 : m_MVP = m_Projection * m_View * m_Model;
285 0 : glGenBuffers(1, &m_VertexBuffer);
286 0 : glGenBuffers(1, &m_ColorBuffer);
287 :
288 0 : CHECK_GL_ERROR();
289 :
290 0 : m_CommonProID = LoadShaders("commonVertexShader", "commonFragmentShader");
291 0 : m_MatrixID = glGetUniformLocation(m_CommonProID, "MVP");
292 0 : m_2DVertexID = glGetAttribLocation(m_CommonProID, "vPosition");
293 0 : m_2DColorID = glGetUniformLocation(m_CommonProID, "vColor");
294 0 : CHECK_GL_ERROR();
295 :
296 : #if DEBUG_POSITIONING
297 : m_DebugProID = LoadShaders("debugVertexShader", "debugFragmentShader");
298 : m_DebugVertexID = glGetAttribLocation(m_DebugProID, "vPosition");
299 : CHECK_GL_ERROR();
300 : #endif
301 :
302 0 : m_BackgroundProID = LoadShaders("backgroundVertexShader", "backgroundFragmentShader");
303 0 : m_BackgroundMatrixID = glGetUniformLocation(m_BackgroundProID, "MVP");
304 0 : m_BackgroundVertexID = glGetAttribLocation(m_BackgroundProID, "vPosition");
305 0 : m_BackgroundColorID = glGetAttribLocation(m_BackgroundProID, "vColor");
306 :
307 0 : CHECK_GL_ERROR();
308 :
309 0 : m_SymbolProID = LoadShaders("symbolVertexShader", "symbolFragmentShader");
310 0 : m_SymbolVertexID = glGetAttribLocation(m_SymbolProID, "vPosition");
311 0 : m_SymbolMatrixID = glGetUniformLocation(m_SymbolProID, "MVP");
312 0 : m_SymbolColorID = glGetUniformLocation(m_SymbolProID, "vColor");
313 0 : m_SymbolShapeID = glGetUniformLocation(m_SymbolProID, "shape");
314 :
315 0 : CHECK_GL_ERROR();
316 :
317 0 : m_TextProID = LoadShaders("textVertexShader", "textFragmentShader");
318 0 : m_TextMatrixID = glGetUniformLocation(m_TextProID, "MVP");
319 0 : m_TextVertexID = glGetAttribLocation(m_TextProID, "vPosition");
320 0 : m_TextTexCoordID = glGetAttribLocation(m_TextProID, "texCoord");
321 0 : m_TextTexID = glGetUniformLocation(m_TextProID, "TextTex");
322 :
323 0 : CHECK_GL_ERROR();
324 :
325 0 : glGenBuffers(1, &m_TextTexCoordBuf);
326 0 : glBindBuffer(GL_ARRAY_BUFFER, m_TextTexCoordBuf);
327 0 : glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW);
328 0 : glBindBuffer(GL_ARRAY_BUFFER, 0);
329 :
330 0 : glEnable(GL_LIGHTING);
331 0 : GLfloat light_direction[] = { 0.0 , 0.0 , 1.0 };
332 0 : GLfloat materialDiffuse[] = { 1.0 , 1.0 , 1.0 , 1.0};
333 0 : glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
334 0 : glMaterialfv(GL_FRONT,GL_DIFFUSE,materialDiffuse);
335 0 : glEnable(GL_LIGHT0);
336 0 : glEnable(GL_NORMALIZE);
337 :
338 0 : return 0;
339 : }
340 :
341 0 : BitmapEx OpenGLRender::GetAsBitmap()
342 : {
343 0 : boost::scoped_array<sal_uInt8> buf(new sal_uInt8[m_iWidth * m_iHeight * 4]);
344 0 : glReadPixels(0, 0, m_iWidth, m_iHeight, GL_BGRA, GL_UNSIGNED_BYTE, buf.get());
345 :
346 0 : Bitmap aBitmap( Size(m_iWidth, m_iHeight), 24 );
347 0 : AlphaMask aAlpha( Size(m_iWidth, m_iHeight) );
348 :
349 : {
350 0 : Bitmap::ScopedWriteAccess pWriteAccess( aBitmap );
351 0 : AlphaMask::ScopedWriteAccess pAlphaWriteAccess( aAlpha );
352 :
353 0 : size_t nCurPos = 0;
354 0 : for( int y = 0; y < m_iHeight; ++y)
355 : {
356 0 : Scanline pScan = pWriteAccess->GetScanline(y);
357 0 : Scanline pAlphaScan = pAlphaWriteAccess->GetScanline(y);
358 0 : for( int x = 0; x < m_iWidth; ++x )
359 : {
360 0 : *pScan++ = buf[nCurPos];
361 0 : *pScan++ = buf[nCurPos+1];
362 0 : *pScan++ = buf[nCurPos+2];
363 :
364 0 : nCurPos += 3;
365 0 : *pAlphaScan++ = static_cast<sal_uInt8>( 255 - buf[nCurPos++] );
366 : }
367 0 : }
368 : }
369 :
370 0 : BitmapEx aBmp(aBitmap, aAlpha);
371 :
372 : #if DEBUG_PNG // debug PNG writing
373 : static int nIdx = 0;
374 : OUString aName = OUString( "file:///home/moggi/Documents/work/" ) + OUString::number( nIdx++ ) + ".png";
375 : try {
376 : vcl::PNGWriter aWriter( aBmp );
377 : SvFileStream sOutput( aName, STREAM_WRITE );
378 : aWriter.Write( sOutput );
379 : sOutput.Close();
380 : } catch (...) {
381 : SAL_WARN("chart2.opengl", "Error writing png to " << aName);
382 : }
383 : #endif
384 :
385 0 : return aBmp;
386 : }
387 :
388 0 : int OpenGLRender::SetLine2DShapePoint(float x, float y, int listLength)
389 : {
390 0 : if (m_Line2DPointList.empty())
391 : {
392 0 : m_Line2DPointList.reserve(listLength*3);
393 : }
394 0 : float actualX = (x / OPENGL_SCALE_VALUE);
395 0 : float actualY = (y / OPENGL_SCALE_VALUE);
396 0 : m_Line2DPointList.push_back(actualX);
397 0 : m_Line2DPointList.push_back(actualY);
398 0 : m_Line2DPointList.push_back(m_fZStep);
399 :
400 0 : if (m_Line2DPointList.size() == size_t(listLength * 3))
401 : {
402 0 : m_Line2DShapePointList.push_back(m_Line2DPointList);
403 0 : m_Line2DPointList.clear();
404 : }
405 0 : return 0;
406 : }
407 :
408 0 : int OpenGLRender::RenderLine2FBO(int)
409 : {
410 0 : CHECK_GL_ERROR();
411 0 : glLineWidth(m_fLineWidth);
412 0 : size_t listNum = m_Line2DShapePointList.size();
413 0 : PosVecf3 trans = {0.0f, 0.0f, 0.0f};
414 0 : PosVecf3 angle = {0.0f, 0.0f, 0.0f};
415 0 : PosVecf3 scale = {1.0f, 1.0f, 1.0f};
416 0 : MoveModelf(trans, angle, scale);
417 0 : m_MVP = m_Projection * m_View * m_Model;
418 0 : for (size_t i = 0; i < listNum; i++)
419 : {
420 0 : Line2DPointList &pointList = m_Line2DShapePointList.front();
421 : //fill vertex buffer
422 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
423 0 : CHECK_GL_ERROR();
424 0 : glBufferData(GL_ARRAY_BUFFER, pointList.size() * sizeof(float), &pointList[0], GL_STATIC_DRAW);
425 0 : CHECK_GL_ERROR();
426 : // Use our shader
427 0 : glUseProgram(m_CommonProID);
428 0 : CHECK_GL_ERROR();
429 :
430 0 : glUniform4fv(m_2DColorID, 1, &m_2DColor[0]);
431 0 : CHECK_GL_ERROR();
432 0 : glUniformMatrix4fv(m_MatrixID, 1, GL_FALSE, &m_MVP[0][0]);
433 : //CHECK_GL_ERROR();
434 :
435 : // 1rst attribute buffer : vertices
436 0 : CHECK_GL_ERROR();
437 : glVertexAttribPointer(
438 : m_2DVertexID,
439 : 3, // size
440 : GL_FLOAT, // type
441 : GL_FALSE, // normalized?
442 : 0, // stride
443 : (void*)0 // array buffer offset
444 0 : );
445 0 : glEnableVertexAttribArray(m_2DVertexID);
446 0 : glDrawArrays(GL_LINE_STRIP, 0, pointList.size()/3); // 12*3 indices starting at 0 -> 12 triangles
447 0 : CHECK_GL_ERROR();
448 0 : glUseProgram(0);
449 0 : glDisableVertexAttribArray(m_2DVertexID);
450 0 : CHECK_GL_ERROR();
451 0 : m_Line2DShapePointList.pop_front();
452 : }
453 : GLenum status;
454 0 : CHECK_GL_ERROR();
455 0 : CHECK_GL_FRAME_BUFFER_STATUS();
456 0 : m_fZStep += Z_STEP;
457 0 : return 0;
458 : }
459 :
460 : #if DEBUG_POSITIONING
461 : void OpenGLRender::renderDebug()
462 : {
463 : CHECK_GL_ERROR();
464 :
465 : GLfloat vertices[4][3] = {
466 : {-0.9, -0.9, 0 },
467 : {-0.6, -0.2, 0 },
468 : {0.3, 0.3, 0 },
469 : {0.9, 0.9, 0 } };
470 :
471 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
472 : CHECK_GL_ERROR();
473 : glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
474 : CHECK_GL_ERROR();
475 : glUseProgram(m_DebugProID);
476 : CHECK_GL_ERROR();
477 : glVertexAttribPointer(m_DebugVertexID, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
478 : CHECK_GL_ERROR();
479 : glEnableVertexAttribArray(m_DebugVertexID);
480 :
481 : glDrawArrays(GL_LINE_STRIP, 0, 3);
482 : CHECK_GL_ERROR();
483 : glDisableVertexAttribArray(m_DebugVertexID);
484 :
485 : CHECK_GL_ERROR();
486 : }
487 : #endif
488 :
489 0 : void OpenGLRender::prepareToRender()
490 : {
491 0 : glViewport(0, 0, m_iWidth, m_iHeight);
492 0 : if (!m_FboID)
493 : {
494 : // create a texture object
495 0 : CreateTextureObj(m_iWidth, m_iHeight);
496 : //create render buffer object
497 0 : CreateRenderObj(m_iWidth, m_iHeight);
498 : //create fbo
499 0 : CreateFrameBufferObj();
500 0 : if (mbArbMultisampleSupported)
501 : {
502 0 : CreateMultiSampleFrameBufObj();
503 : }
504 : }
505 : //bind fbo
506 0 : if (mbArbMultisampleSupported)
507 : {
508 0 : glBindFramebuffer(GL_FRAMEBUFFER,m_frameBufferMS);
509 : }
510 : else
511 : {
512 0 : glBindFramebuffer(GL_FRAMEBUFFER, m_FboID);
513 : }
514 :
515 : // Clear the screen
516 0 : glClearDepth(1.0f);
517 0 : glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
518 0 : m_fZStep = 0;
519 0 : }
520 :
521 0 : void OpenGLRender::renderToBitmap()
522 : {
523 0 : if (mbArbMultisampleSupported)
524 : {
525 : GLenum status;
526 0 : glBindFramebuffer(GL_FRAMEBUFFER, 0);
527 0 : glBindFramebuffer(GL_READ_FRAMEBUFFER, m_frameBufferMS);
528 0 : status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
529 0 : if (status != GL_FRAMEBUFFER_COMPLETE)
530 : {
531 : SAL_INFO("chart2.opengl", "The frame buffer status is not complete!");
532 : }
533 0 : glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FboID);
534 0 : status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
535 0 : if (status != GL_FRAMEBUFFER_COMPLETE)
536 : {
537 : SAL_INFO("chart2.opengl", "The frame buffer status is not complete!");
538 : }
539 0 : glBlitFramebuffer(0, 0 ,m_iWidth, m_iHeight, 0, 0,m_iWidth ,m_iHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
540 0 : glBindFramebuffer(GL_READ_FRAMEBUFFER,0);
541 0 : glBindFramebuffer(GL_DRAW_FRAMEBUFFER,0);
542 : }
543 0 : glBindFramebuffer(GL_FRAMEBUFFER, m_FboID);
544 :
545 : #if RENDER_TO_FILE
546 : char fileName[256] = {0};
547 : sprintf(fileName, "D:\\shaderout_%d_%d.bmp", m_iWidth, m_iHeight);
548 : sal_uInt8 *buf = (sal_uInt8 *)malloc(m_iWidth * m_iHeight * 3 + BMP_HEADER_LEN);
549 : CreateBMPHeader(buf, m_iWidth, m_iHeight);
550 : glReadPixels(0, 0, m_iWidth, m_iHeight, GL_BGR, GL_UNSIGNED_BYTE, buf + BMP_HEADER_LEN);
551 : FILE *pfile = fopen(fileName,"wb");
552 : fwrite(buf,m_iWidth * m_iHeight * 3 + BMP_HEADER_LEN, 1, pfile);
553 : free(buf);
554 : fclose(pfile);
555 : #else
556 0 : Graphic aGraphic( GetAsBitmap() );
557 0 : uno::Reference< awt::XBitmap> xBmp( aGraphic.GetXGraphic(), uno::UNO_QUERY );
558 0 : uno::Reference < beans::XPropertySet > xPropSet ( mxRenderTarget, uno::UNO_QUERY );
559 0 : xPropSet->setPropertyValue("Graphic", uno::makeAny(aGraphic.GetXGraphic()));
560 0 : mxRenderTarget->setSize(awt::Size(m_iWidth*OPENGL_SCALE_VALUE, m_iHeight*OPENGL_SCALE_VALUE));
561 0 : mxRenderTarget->setPosition(awt::Point(0,0));
562 : #endif
563 0 : glBindFramebuffer(GL_FRAMEBUFFER, 0);
564 0 : }
565 :
566 0 : int OpenGLRender::CreateTextureObj(int width, int height)
567 : {
568 0 : glGenTextures(1, &m_TextureObj);
569 0 : glBindTexture(GL_TEXTURE_2D, m_TextureObj);
570 0 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
571 0 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
572 0 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
573 0 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
574 0 : glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
575 0 : CHECK_GL_ERROR();
576 0 : glBindTexture(GL_TEXTURE_2D, 0);
577 0 : return 0;
578 : }
579 :
580 0 : int OpenGLRender::CreateRenderObj(int width, int height)
581 : {
582 0 : glGenRenderbuffers(1, &m_RboID);
583 0 : CHECK_GL_ERROR();
584 0 : glBindRenderbuffer(GL_RENDERBUFFER, m_RboID);
585 0 : CHECK_GL_ERROR();
586 0 : glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
587 0 : CHECK_GL_ERROR();
588 0 : glBindRenderbuffer(GL_RENDERBUFFER, 0);
589 0 : CHECK_GL_ERROR();
590 0 : return 0;
591 : }
592 :
593 0 : int OpenGLRender::MoveModelf(PosVecf3 trans, PosVecf3 angle, PosVecf3 scale)
594 : {
595 0 : glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
596 0 : glm::mat4 aScaleMatrix = glm::scale(glm::vec3(scale.x, scale.y, scale.z));
597 0 : glm::mat4 aRotationMatrix = glm::eulerAngleYXZ(angle.y, angle.x, angle.z);
598 0 : m_Model = aTranslationMatrix * aRotationMatrix * aScaleMatrix;
599 0 : return 0;
600 : }
601 :
602 0 : int OpenGLRender::CreateFrameBufferObj()
603 : {
604 : GLenum status;
605 : // create a framebuffer object, you need to delete them when program exits.
606 0 : glGenFramebuffers(1, &m_FboID);
607 0 : CHECK_GL_FRAME_BUFFER_STATUS();
608 0 : glBindFramebuffer(GL_FRAMEBUFFER, m_FboID);
609 0 : glBindTexture(GL_TEXTURE_2D, m_TextureObj);
610 : // attach a texture to FBO color attachement point
611 0 : glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_TextureObj, 0);
612 0 : CHECK_GL_FRAME_BUFFER_STATUS();
613 0 : glBindTexture(GL_TEXTURE_2D, 0);
614 : // attach a renderbuffer to depth attachment point
615 0 : glBindRenderbuffer(GL_RENDERBUFFER, m_RboID);
616 0 : glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_RboID);
617 0 : CHECK_GL_FRAME_BUFFER_STATUS();
618 0 : glBindRenderbuffer(GL_RENDERBUFFER, 0);
619 0 : glBindFramebuffer(GL_FRAMEBUFFER, 0);
620 :
621 0 : return 0;
622 : }
623 :
624 0 : void OpenGLRender::Release()
625 : {
626 0 : glDeleteBuffers(1, &m_VertexBuffer);
627 0 : glDeleteBuffers(1, &m_ColorBuffer);
628 0 : glDeleteBuffers(1, &m_TextTexCoordBuf);
629 0 : glDeleteProgram(m_CommonProID);
630 0 : glDeleteProgram(m_TextProID);
631 0 : glDeleteProgram(m_BackgroundProID);
632 0 : glDeleteProgram(m_SymbolProID);
633 0 : glDeleteFramebuffers(1, &m_FboID);
634 0 : glDeleteFramebuffers(1, &m_frameBufferMS);
635 0 : glDeleteTextures(1, &m_TextureObj);
636 0 : glDeleteRenderbuffers(1, &m_RboID);
637 0 : glDeleteRenderbuffers(1, &m_renderBufferColorMS);
638 0 : glDeleteRenderbuffers(1, &m_renderBufferDepthMS);
639 0 : }
640 :
641 0 : OpenGLRender::OpenGLRender(uno::Reference< drawing::XShape > xTarget)
642 : : m_Model(glm::mat4(1.0f))
643 : , m_TextureObj(0)
644 : , m_FboID(0)
645 : , m_RboID(0)
646 : , m_iWidth(0)
647 : , m_iHeight(0)
648 : , m_fLineWidth(0.001f)
649 : , mxRenderTarget(xTarget)
650 : , mbArbMultisampleSupported(false)
651 : #if defined( _WIN32 )
652 : , m_iArbMultisampleFormat(0)
653 : #endif
654 : , m_2DColor(glm::vec4(1.0, 0.0, 0.0, 1.0))
655 : , m_frameBufferMS(0)
656 : , m_renderBufferColorMS(0)
657 : , m_renderBufferDepthMS(0)
658 : , m_CommonProID(0)
659 : , m_2DVertexID(0)
660 : , m_2DColorID(0)
661 : , m_fZStep(0)
662 : , m_TextProID(0)
663 : , m_TextMatrixID(0)
664 : , m_TextVertexID(0)
665 : , m_TextTexCoordID(0)
666 : , m_TextTexCoordBuf(0)
667 : , m_TextTexID(0)
668 : , m_BackgroundProID(0)
669 : , m_BackgroundMatrixID(0)
670 : , m_BackgroundVertexID(0)
671 : , m_BackgroundColorID(0)
672 : , m_SymbolProID(0)
673 : , m_SymbolVertexID(0)
674 : , m_SymbolMatrixID(0)
675 : , m_SymbolColorID(0)
676 0 : , m_SymbolShapeID(0)
677 : {
678 : //TODO: moggi: use STL
679 0 : memset(&m_Bubble2DCircle, 0, sizeof(m_Bubble2DCircle));
680 :
681 : //TODO: moggi: use STL
682 0 : for (size_t i = 0; i < sizeof(m_BackgroundColor) / sizeof(float); i++)
683 : {
684 0 : m_BackgroundColor[i] = 1.0;
685 : }
686 :
687 0 : mxRenderTarget->setPosition(awt::Point(0,0));
688 0 : }
689 :
690 0 : OpenGLRender::~OpenGLRender()
691 : {
692 0 : Release();
693 0 : }
694 :
695 : // TODO: moggi: that screws up FBO if called after buffers have been created!!!!
696 0 : void OpenGLRender::SetSize(int width, int height)
697 : {
698 0 : m_iWidth = width;
699 0 : m_iHeight = height;
700 0 : m_Projection = glm::ortho(0.f, float(m_iWidth), 0.f, float(m_iHeight), -4.f, 3.f);
701 0 : }
702 :
703 : #if RENDER_TO_FILE
704 : int OpenGLRender::CreateBMPHeader(sal_uInt8 *bmpHeader, int xsize, int ysize)
705 : {
706 : unsigned char header[BMP_HEADER_LEN] = {
707 : 0x42, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0,
708 : 54, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0,
709 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
710 : 0, 0, 0, 0
711 : };
712 :
713 : long file_size = (long)xsize * (long)ysize * 3 + 54;
714 : header[2] = (unsigned char)(file_size &0x000000ff);
715 : header[3] = (file_size >> 8) & 0x000000ff;
716 : header[4] = (file_size >> 16) & 0x000000ff;
717 : header[5] = (file_size >> 24) & 0x000000ff;
718 :
719 : long width = xsize;
720 : header[18] = width & 0x000000ff;
721 : header[19] = (width >> 8) &0x000000ff;
722 : header[20] = (width >> 16) &0x000000ff;
723 : header[21] = (width >> 24) &0x000000ff;
724 :
725 : long height = -ysize;
726 : header[22] = height &0x000000ff;
727 : header[23] = (height >> 8) &0x000000ff;
728 : header[24] = (height >> 16) &0x000000ff;
729 : header[25] = (height >> 24) &0x000000ff;
730 : memcpy(bmpHeader, header, BMP_HEADER_LEN);
731 : return 0;
732 : }
733 : #endif
734 :
735 0 : void OpenGLRender::SetLine2DColor(sal_uInt8 r, sal_uInt8 g, sal_uInt8 b, sal_uInt8 nAlpha)
736 : {
737 0 : m_2DColor = glm::vec4((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, nAlpha/255.f);
738 0 : }
739 :
740 0 : void OpenGLRender::SetLine2DWidth(int width)
741 : {
742 0 : m_fLineWidth = std::max((float)width / OPENGL_SCALE_VALUE, 0.001f);
743 0 : }
744 :
745 0 : void OpenGLRender::SetColor(sal_uInt32 color, sal_uInt8 nAlpha)
746 : {
747 0 : sal_uInt8 r = (color & 0x00FF0000) >> 16;
748 0 : sal_uInt8 g = (color & 0x0000FF00) >> 8;
749 0 : sal_uInt8 b = (color & 0x000000FF);
750 0 : m_2DColor = glm::vec4((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, nAlpha/ 255.f);
751 0 : }
752 :
753 0 : int OpenGLRender::CreateMultiSampleFrameBufObj()
754 : {
755 0 : glGenFramebuffers(1, &m_frameBufferMS);
756 0 : glBindFramebuffer(GL_FRAMEBUFFER, m_frameBufferMS);
757 :
758 0 : glGenRenderbuffers(1, &m_renderBufferColorMS);
759 0 : glBindRenderbuffer(GL_RENDERBUFFER, m_renderBufferColorMS);
760 0 : glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_RGB, m_iWidth, m_iHeight);
761 0 : glBindRenderbuffer(GL_RENDERBUFFER, 0);
762 0 : glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderBufferColorMS);
763 :
764 0 : glGenRenderbuffers(1, &m_renderBufferDepthMS);
765 0 : glBindRenderbuffer(GL_RENDERBUFFER, m_renderBufferDepthMS);
766 0 : glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_DEPTH_COMPONENT24, m_iWidth, m_iHeight);
767 0 : glBindRenderbuffer(GL_RENDERBUFFER, 0);
768 0 : glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_renderBufferDepthMS);
769 0 : glBindFramebuffer(GL_FRAMEBUFFER, 0);
770 :
771 0 : return 0;
772 : }
773 :
774 0 : int OpenGLRender::Create2DCircle(int detail)
775 : {
776 : float angle;
777 0 : if (detail <= 0)
778 : {
779 0 : return -1;
780 : }
781 0 : m_Bubble2DCircle.clear();
782 0 : m_Bubble2DCircle.reserve(2 * (detail + 3));
783 0 : m_Bubble2DCircle.push_back(0);
784 0 : m_Bubble2DCircle.push_back(0);
785 0 : for(angle = 2.0f * GL_PI; angle > -(2.0f * GL_PI / detail); angle -= (2.0f * GL_PI / detail))
786 : {
787 0 : m_Bubble2DCircle.push_back(sin(angle));
788 0 : m_Bubble2DCircle.push_back(cos(angle));
789 : }
790 0 : return 0;
791 : }
792 :
793 0 : int OpenGLRender::Bubble2DShapePoint(float x, float y, float directionX, float directionY)
794 : {
795 : //check whether to create the circle data
796 0 : if (m_Bubble2DCircle.empty())
797 : {
798 0 : Create2DCircle(100);
799 : }
800 :
801 0 : float actualX = (x / OPENGL_SCALE_VALUE);
802 0 : float actualY = (y / OPENGL_SCALE_VALUE);
803 : Bubble2DPointList aBubble2DPointList;
804 0 : aBubble2DPointList.xScale = directionX / OPENGL_SCALE_VALUE;
805 0 : aBubble2DPointList.yScale = directionY / OPENGL_SCALE_VALUE;
806 0 : aBubble2DPointList.x = actualX + aBubble2DPointList.xScale / 2;
807 0 : aBubble2DPointList.y = actualY + aBubble2DPointList.yScale / 2;
808 :
809 0 : m_Bubble2DShapePointList.push_back(aBubble2DPointList);
810 0 : return 0;
811 : }
812 :
813 0 : int OpenGLRender::RenderBubble2FBO(int)
814 : {
815 0 : CHECK_GL_ERROR();
816 0 : glm::vec4 edgeColor = glm::vec4(0.0, 0.0, 0.0, 1.0);
817 0 : size_t listNum = m_Bubble2DShapePointList.size();
818 0 : for (size_t i = 0; i < listNum; i++)
819 : {
820 : //move the circle to the pos, and scale using the xScale and Y scale
821 0 : Bubble2DPointList &pointList = m_Bubble2DShapePointList.front();
822 0 : PosVecf3 trans = {pointList.x, pointList.y, m_fZStep};
823 0 : PosVecf3 angle = {0.0f, 0.0f, 0.0f};
824 0 : PosVecf3 scale = {pointList.xScale / 2, pointList.yScale / 2 , 1.0f};
825 0 : MoveModelf(trans, angle, scale);
826 0 : m_MVP = m_Projection * m_View * m_Model;
827 : //render to fbo
828 : //fill vertex buffer
829 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
830 0 : if (m_Bubble2DCircle.empty())
831 : {
832 0 : Create2DCircle(100);
833 : }
834 0 : glBufferData(GL_ARRAY_BUFFER, m_Bubble2DCircle.size() * sizeof(GLfloat), &m_Bubble2DCircle[0], GL_STATIC_DRAW);
835 :
836 0 : glUseProgram(m_CommonProID);
837 :
838 0 : glUniform4fv(m_2DColorID, 1, &m_2DColor[0]);
839 :
840 0 : glUniformMatrix4fv(m_MatrixID, 1, GL_FALSE, &m_MVP[0][0]);
841 : // 1rst attribute buffer : vertices
842 0 : glEnableVertexAttribArray(m_2DVertexID);
843 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
844 : glVertexAttribPointer(
845 : m_2DVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
846 : 2, // size
847 : GL_FLOAT, // type
848 : GL_FALSE, // normalized?
849 : 0, // stride
850 : (void*)0 // array buffer offset
851 0 : );
852 0 : glDrawArrays(GL_TRIANGLE_FAN, 0, m_Bubble2DCircle.size() / 2);
853 0 : glDisableVertexAttribArray(m_2DVertexID);
854 0 : glUseProgram(0);
855 0 : glBindBuffer(GL_ARRAY_BUFFER, 0);
856 : //add black edge
857 0 : glLineWidth(3.0);
858 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
859 0 : glBufferData(GL_ARRAY_BUFFER, m_Bubble2DCircle.size() * sizeof(GLfloat) -2 , &m_Bubble2DCircle[2], GL_STATIC_DRAW);
860 0 : glUseProgram(m_CommonProID);
861 0 : glUniform4fv(m_2DColorID, 1, &edgeColor[0]);
862 0 : glUniformMatrix4fv(m_MatrixID, 1, GL_FALSE, &m_MVP[0][0]);
863 0 : glEnableVertexAttribArray(m_2DVertexID);
864 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
865 : glVertexAttribPointer(
866 : m_2DVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
867 : 2, // size
868 : GL_FLOAT, // type
869 : GL_FALSE, // normalized?
870 : 0, // stride
871 : (void*)0 // array buffer offset
872 0 : );
873 0 : glDrawArrays(GL_LINE_STRIP, 0, (m_Bubble2DCircle.size() * sizeof(GLfloat) -2) / sizeof(float) / 2);
874 0 : glDisableVertexAttribArray(m_2DVertexID);
875 0 : glUseProgram(0);
876 0 : glBindBuffer(GL_ARRAY_BUFFER, 0);
877 0 : m_Bubble2DShapePointList.pop_front();
878 0 : glLineWidth(m_fLineWidth);
879 : }
880 : //if use MSAA, we should copy the data to the FBO texture
881 0 : GLenum fbResult = glCheckFramebufferStatus(GL_FRAMEBUFFER);
882 0 : if( fbResult != GL_FRAMEBUFFER_COMPLETE )
883 : {
884 : SAL_WARN("chart2.opengl", "error");
885 0 : return -1;
886 : }
887 0 : CHECK_GL_ERROR();
888 0 : m_fZStep += Z_STEP;
889 0 : return 0;
890 : }
891 :
892 0 : int OpenGLRender::RectangleShapePoint(float x, float y, float directionX, float directionY)
893 : {
894 : //check whether to create the circle data
895 0 : float actualX = x / OPENGL_SCALE_VALUE;
896 0 : float actualY = y / OPENGL_SCALE_VALUE;
897 0 : float actualSizeX = directionX / OPENGL_SCALE_VALUE;
898 0 : float actualSizeY = directionY / OPENGL_SCALE_VALUE;
899 : RectanglePointList aRectangle;
900 :
901 0 : aRectangle.points[0] = actualX;
902 0 : aRectangle.points[1] = actualY;
903 0 : aRectangle.points[2] = m_fZStep;
904 0 : aRectangle.points[3] = actualX + actualSizeX;
905 0 : aRectangle.points[4] = actualY;
906 0 : aRectangle.points[5] = m_fZStep;
907 0 : aRectangle.points[6] = actualX + actualSizeX;
908 0 : aRectangle.points[7] = actualY + actualSizeY;
909 0 : aRectangle.points[8] = m_fZStep;
910 0 : aRectangle.points[9] = actualX;
911 0 : aRectangle.points[10] = actualY + actualSizeY;
912 0 : aRectangle.points[11] = m_fZStep;
913 :
914 0 : m_RectangleShapePointList.push_back(aRectangle);
915 0 : return 0;
916 : }
917 :
918 0 : int OpenGLRender::RenderRectangleShape(bool bBorder, bool bFill)
919 : {
920 0 : size_t listNum = m_RectangleShapePointList.size();
921 0 : for (size_t i = 0; i < listNum; i++)
922 : {
923 : //move the circle to the pos, and scale using the xScale and Y scale
924 0 : RectanglePointList &pointList = m_RectangleShapePointList.front();
925 : {
926 0 : PosVecf3 trans = {0, 0, 0};
927 0 : PosVecf3 angle = {0.0f, 0.0f, 0.0f};
928 0 : PosVecf3 scale = {1, 1, 1.0f};
929 0 : MoveModelf(trans, angle, scale);
930 0 : m_MVP = m_Projection * m_View * m_Model;
931 : }
932 :
933 : //render to fbo
934 : //fill vertex buffer
935 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
936 0 : glBufferData(GL_ARRAY_BUFFER, sizeof(pointList.points), pointList.points, GL_STATIC_DRAW);
937 :
938 0 : glBindBuffer(GL_ARRAY_BUFFER, m_ColorBuffer);
939 0 : glBufferData(GL_ARRAY_BUFFER, sizeof(m_BackgroundColor), m_BackgroundColor, GL_STATIC_DRAW);
940 0 : glUseProgram(m_BackgroundProID);
941 :
942 0 : glUniformMatrix4fv(m_BackgroundMatrixID, 1, GL_FALSE, &m_MVP[0][0]);
943 0 : if(bFill)
944 : {
945 0 : glEnableVertexAttribArray(m_BackgroundVertexID);
946 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
947 : glVertexAttribPointer(
948 : m_BackgroundVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
949 : 3, // size
950 : GL_FLOAT, // type
951 : GL_FALSE, // normalized?
952 : 0, // stride
953 : (void*)0 // array buffer offset
954 0 : );
955 :
956 : // 2nd attribute buffer : color
957 0 : glEnableVertexAttribArray(m_BackgroundColorID);
958 0 : glBindBuffer(GL_ARRAY_BUFFER, m_ColorBuffer);
959 : glVertexAttribPointer(
960 : m_BackgroundColorID, // attribute. No particular reason for 0, but must match the layout in the shader.
961 : 4, // size
962 : GL_FLOAT, // type
963 : GL_FALSE, // normalized?
964 : 0, // stride
965 : (void*)0 // array buffer offset
966 0 : );
967 : //TODO: moggi: get rid of GL_QUADS
968 0 : glDrawArrays(GL_QUADS, 0, 4);
969 0 : glDisableVertexAttribArray(m_BackgroundVertexID);
970 0 : glDisableVertexAttribArray(m_BackgroundColorID);
971 : }
972 0 : if(bBorder)
973 : {
974 0 : if(bFill)
975 : {
976 0 : PosVecf3 trans = {0.0, 0.0, Z_STEP };
977 0 : PosVecf3 angle = {0.0f, 0.0f, 0.0f};
978 0 : PosVecf3 scale = {1, 1, 1.0f};
979 0 : MoveModelf(trans, angle, scale);
980 0 : m_MVP = m_Projection * m_View * m_Model;
981 :
982 0 : m_fZStep += Z_STEP;
983 0 : glUniformMatrix4fv(m_BackgroundMatrixID, 1, GL_FALSE, &m_MVP[0][0]);
984 : }
985 0 : SetBackGroundColor(COL_BLACK, COL_BLACK, 255);
986 :
987 0 : glBindBuffer(GL_ARRAY_BUFFER, m_ColorBuffer);
988 0 : glBufferData(GL_ARRAY_BUFFER, sizeof(m_BackgroundColor), m_BackgroundColor, GL_STATIC_DRAW);
989 : // 1rst attribute buffer : vertices
990 0 : glEnableVertexAttribArray(m_BackgroundVertexID);
991 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
992 : glVertexAttribPointer(
993 : m_BackgroundVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
994 : 3, // size
995 : GL_FLOAT, // type
996 : GL_FALSE, // normalized?
997 : 0, // stride
998 : (void*)0 // array buffer offset
999 0 : );
1000 :
1001 : // 2nd attribute buffer : color
1002 0 : glEnableVertexAttribArray(m_BackgroundColorID);
1003 0 : glBindBuffer(GL_ARRAY_BUFFER, m_ColorBuffer);
1004 : glVertexAttribPointer(
1005 : m_BackgroundColorID, // attribute. No particular reason for 0, but must match the layout in the shader.
1006 : 4, // size
1007 : GL_FLOAT, // type
1008 : GL_FALSE, // normalized?
1009 : 0, // stride
1010 : (void*)0 // array buffer offset
1011 0 : );
1012 0 : glDrawArrays(GL_LINE_LOOP, 0, 4);
1013 0 : glDisableVertexAttribArray(m_BackgroundVertexID);
1014 0 : glDisableVertexAttribArray(m_BackgroundColorID);
1015 : }
1016 0 : glDisableVertexAttribArray(m_BackgroundVertexID);
1017 0 : glDisableVertexAttribArray(m_BackgroundColorID);
1018 0 : glUseProgram(0);
1019 0 : glBindBuffer(GL_ARRAY_BUFFER, 0);
1020 0 : m_RectangleShapePointList.pop_front();
1021 : }
1022 0 : CHECK_GL_ERROR();
1023 :
1024 0 : m_fZStep += Z_STEP;
1025 0 : return 0;
1026 : }
1027 :
1028 0 : int OpenGLRender::CreateTextTexture(const BitmapEx& rBitmapEx, const awt::Point&, const awt::Size& aSize, long rotation,
1029 : const drawing::HomogenMatrix3& rTrans)
1030 : {
1031 : #if DEBUG_PNG // debug PNG writing
1032 : static int nIdx = 0;
1033 : OUString aName = OUString( "file:///home/moggi/Documents/work/text" ) + OUString::number( nIdx++ ) + ".png";
1034 : try {
1035 : vcl::PNGWriter aWriter( rBitmapEx );
1036 : SvFileStream sOutput( aName, STREAM_WRITE );
1037 : aWriter.Write( sOutput );
1038 : sOutput.Close();
1039 : } catch (...) {
1040 : SAL_WARN("chart2.opengl", "Error writing png to " << aName);
1041 : }
1042 : #endif
1043 :
1044 0 : long bmpWidth = rBitmapEx.GetSizePixel().Width();
1045 0 : long bmpHeight = rBitmapEx.GetSizePixel().Height();
1046 :
1047 0 : Bitmap aBitmap (rBitmapEx.GetBitmap());
1048 0 : AlphaMask aAlpha (rBitmapEx.GetAlpha());
1049 0 : boost::scoped_array<sal_uInt8> bitmapBuf(new sal_uInt8[4* bmpWidth * bmpHeight ]);
1050 0 : Bitmap::ScopedReadAccess pReadAccces( aBitmap );
1051 0 : AlphaMask::ScopedReadAccess pAlphaReadAccess( aAlpha );
1052 :
1053 0 : size_t i = 0;
1054 0 : for (long ny = 0; ny < bmpHeight; ny++)
1055 : {
1056 0 : Scanline pAScan = pAlphaReadAccess->GetScanline(ny);
1057 0 : for(long nx = 0; nx < bmpWidth; nx++)
1058 : {
1059 0 : BitmapColor aCol = pReadAccces->GetColor( ny, nx );
1060 0 : bitmapBuf[i++] = aCol.GetRed();
1061 0 : bitmapBuf[i++] = aCol.GetGreen();
1062 0 : bitmapBuf[i++] = aCol.GetBlue();
1063 0 : bitmapBuf[i++] = 255 - *pAScan++;
1064 0 : }
1065 : }
1066 :
1067 : TextInfo aTextInfo;
1068 0 : aTextInfo.rotation = -(double)rotation / 360.0 * 2* GL_PI;
1069 0 : aTextInfo.vertex[0] = -aSize.Width / 2 / OPENGL_SCALE_VALUE;
1070 0 : aTextInfo.vertex[1] = -aSize.Height / 2 / OPENGL_SCALE_VALUE;
1071 0 : aTextInfo.vertex[2] = m_fZStep;
1072 :
1073 0 : aTextInfo.vertex[3] = aSize.Width / 2 / OPENGL_SCALE_VALUE ;
1074 0 : aTextInfo.vertex[4] = -aSize.Height / 2 / OPENGL_SCALE_VALUE;
1075 0 : aTextInfo.vertex[5] = m_fZStep;
1076 :
1077 0 : aTextInfo.vertex[6] = aSize.Width / 2 / OPENGL_SCALE_VALUE;
1078 0 : aTextInfo.vertex[7] = aSize.Height / 2 / OPENGL_SCALE_VALUE;
1079 0 : aTextInfo.vertex[8] = m_fZStep;
1080 :
1081 0 : aTextInfo.vertex[9] = -aSize.Width / 2 / OPENGL_SCALE_VALUE;
1082 0 : aTextInfo.vertex[10] = aSize.Height / 2 / OPENGL_SCALE_VALUE;
1083 0 : aTextInfo.vertex[11] = m_fZStep;
1084 0 : aTextInfo.nDx = (rTrans.Line1.Column3 + aSize.Width / 2 ) / OPENGL_SCALE_VALUE - bmpWidth/2;
1085 0 : aTextInfo.nDy = (rTrans.Line2.Column3 + aSize.Height / 2 ) / OPENGL_SCALE_VALUE - bmpHeight/2;
1086 :
1087 0 : CHECK_GL_ERROR();
1088 0 : glGenTextures(1, &aTextInfo.texture);
1089 0 : CHECK_GL_ERROR();
1090 0 : glBindTexture(GL_TEXTURE_2D, aTextInfo.texture);
1091 0 : CHECK_GL_ERROR();
1092 0 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1093 0 : CHECK_GL_ERROR();
1094 0 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1095 0 : CHECK_GL_ERROR();
1096 0 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1097 0 : CHECK_GL_ERROR();
1098 0 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1099 0 : CHECK_GL_ERROR();
1100 0 : glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bmpWidth, bmpHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmapBuf.get());
1101 0 : CHECK_GL_ERROR();
1102 0 : glBindTexture(GL_TEXTURE_2D, 0);
1103 0 : CHECK_GL_ERROR();
1104 0 : m_TextInfoList.push_back(aTextInfo);
1105 0 : return 0;
1106 : }
1107 :
1108 0 : int OpenGLRender::RenderTextShape()
1109 : {
1110 0 : CHECK_GL_ERROR();
1111 0 : size_t listNum = m_TextInfoList.size();
1112 0 : for (size_t i = 0; i < listNum; i++)
1113 : {
1114 0 : TextInfo &textInfo = m_TextInfoList.front();
1115 0 : PosVecf3 trans = { textInfo.nDx, textInfo.nDy, 0};
1116 0 : PosVecf3 angle = {0.0f, 0.0f, float(textInfo.rotation)};
1117 0 : PosVecf3 scale = {1.0, 1.0, 1.0f};
1118 0 : MoveModelf(trans, angle, scale);
1119 0 : m_MVP = m_Projection * m_View * m_Model;
1120 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
1121 0 : CHECK_GL_ERROR();
1122 0 : glBufferData(GL_ARRAY_BUFFER, sizeof(textInfo.vertex), textInfo.vertex, GL_STATIC_DRAW);
1123 0 : CHECK_GL_ERROR();
1124 0 : glUseProgram(m_TextProID);
1125 :
1126 0 : CHECK_GL_ERROR();
1127 0 : glUniformMatrix4fv(m_TextMatrixID, 1, GL_FALSE, &m_MVP[0][0]);
1128 : // 1rst attribute buffer : vertices
1129 0 : glEnableVertexAttribArray(m_TextVertexID);
1130 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
1131 : glVertexAttribPointer(
1132 : m_TextVertexID,
1133 : 3, // size
1134 : GL_FLOAT, // type
1135 : GL_FALSE, // normalized?
1136 : 0, // stride
1137 : (void*)0 // array buffer offset
1138 0 : );
1139 : //tex coord
1140 0 : CHECK_GL_ERROR();
1141 0 : glEnableVertexAttribArray(m_TextTexCoordID);
1142 0 : glBindBuffer(GL_ARRAY_BUFFER, m_TextTexCoordBuf);
1143 : glVertexAttribPointer(
1144 : m_TextTexCoordID,
1145 : 2, // size
1146 : GL_FLOAT, // type
1147 : GL_FALSE, // normalized?
1148 : 0, // stride
1149 : (void*)0 // array buffer offset
1150 0 : );
1151 : //texture
1152 0 : CHECK_GL_ERROR();
1153 0 : glBindTexture(GL_TEXTURE_2D, textInfo.texture);
1154 0 : CHECK_GL_ERROR();
1155 0 : glUniform1i(m_TextTexID, 0);
1156 0 : CHECK_GL_ERROR();
1157 : //TODO: moggi: get rid fo GL_QUADS
1158 0 : glDrawArrays(GL_QUADS, 0, 4);
1159 0 : CHECK_GL_ERROR();
1160 0 : glDisableVertexAttribArray(m_TextTexCoordID);
1161 0 : CHECK_GL_ERROR();
1162 0 : glDisableVertexAttribArray(m_TextVertexID);
1163 0 : CHECK_GL_ERROR();
1164 0 : glBindTexture(GL_TEXTURE_2D, 0);
1165 0 : glUseProgram(0);
1166 0 : glDeleteTextures(1, &textInfo.texture);
1167 0 : CHECK_GL_ERROR();
1168 0 : m_TextInfoList.pop_front();
1169 : }
1170 0 : CHECK_GL_ERROR();
1171 0 : m_fZStep += Z_STEP;
1172 0 : return 0;
1173 : }
1174 :
1175 0 : int OpenGLRender::SetArea2DShapePoint(float x, float y, int listLength)
1176 : {
1177 0 : if (m_Area2DPointList.empty())
1178 : {
1179 0 : m_Area2DPointList.reserve(listLength);
1180 : }
1181 0 : float actualX = (x / OPENGL_SCALE_VALUE);
1182 0 : float actualY = (y / OPENGL_SCALE_VALUE);
1183 0 : m_Area2DPointList.push_back(actualX);
1184 0 : m_Area2DPointList.push_back(actualY);
1185 0 : m_Area2DPointList.push_back(m_fZStep);
1186 :
1187 0 : if (m_Area2DPointList.size() == size_t(listLength * 3))
1188 : {
1189 0 : m_Area2DShapePointList.push_back(m_Area2DPointList);
1190 0 : m_Area2DPointList.clear();
1191 : }
1192 0 : return 0;
1193 : }
1194 :
1195 : namespace {
1196 :
1197 : // only 2D
1198 0 : bool checkCCW(const Area2DPointList& rPoints)
1199 : {
1200 0 : if(rPoints.size() < 3)
1201 0 : return true;
1202 :
1203 0 : GLfloat sum = 0;
1204 0 : for(size_t i = 1; i < rPoints.size()/3; i += 3)
1205 : {
1206 0 : GLfloat x1 = rPoints[(i-1)*3];
1207 0 : GLfloat x2 = rPoints[i*3];
1208 0 : GLfloat y1 = rPoints[(i-1)*3 + 1];
1209 0 : GLfloat y2 = rPoints[i*3 + 1];
1210 0 : GLfloat prod = (x2-x1)*(y2+y1);
1211 :
1212 0 : sum += prod;
1213 : }
1214 :
1215 0 : return (sum <= 0);
1216 : }
1217 :
1218 : }
1219 :
1220 0 : int OpenGLRender::RenderArea2DShape()
1221 : {
1222 0 : CHECK_GL_ERROR();
1223 :
1224 0 : glDisable(GL_MULTISAMPLE);
1225 0 : size_t listNum = m_Area2DShapePointList.size();
1226 0 : PosVecf3 trans = {0.0f, 0.0f, 0.0f};
1227 0 : PosVecf3 angle = {0.0f, 0.0f, 0.0f};
1228 0 : PosVecf3 scale = {1.0f, 1.0f, 1.0f};
1229 0 : MoveModelf(trans, angle, scale);
1230 0 : m_MVP = m_Projection * m_View * m_Model;
1231 0 : for (size_t i = 0; i < listNum; ++i)
1232 : {
1233 0 : Area2DPointList &pointList = m_Area2DShapePointList.front();
1234 0 : bool bIsCCW = checkCCW(pointList); // is it counter clockwise (CCW) or clockwise (CW)
1235 0 : if(!bIsCCW)
1236 0 : glFrontFace(GL_CW);
1237 : //fill vertex buffer
1238 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
1239 0 : glBufferData(GL_ARRAY_BUFFER, pointList.size() * sizeof(float), &pointList[0], GL_STATIC_DRAW);
1240 : // Use our shader
1241 0 : glUseProgram(m_CommonProID);
1242 :
1243 0 : glUniform4fv(m_2DColorID, 1, &m_2DColor[0]);
1244 :
1245 0 : glUniformMatrix4fv(m_MatrixID, 1, GL_FALSE, &m_MVP[0][0]);
1246 :
1247 : // 1rst attribute buffer : vertices
1248 0 : glEnableVertexAttribArray(m_2DVertexID);
1249 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
1250 : glVertexAttribPointer(
1251 : m_2DVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
1252 : 3, // size
1253 : GL_FLOAT, // type
1254 : GL_FALSE, // normalized?
1255 : 0, // stride
1256 : (void*)0 // array buffer offset
1257 0 : );
1258 : // TODO: moggi: remove deprecated GL_POLYGON
1259 0 : glDrawArrays(GL_POLYGON, 0, pointList.size() / 3); // 12*3 indices starting at 0 -> 12 triangles
1260 0 : glDisableVertexAttribArray(m_2DVertexID);
1261 0 : glUseProgram(0);
1262 0 : if(!bIsCCW)
1263 0 : glFrontFace(GL_CCW);
1264 0 : m_Area2DShapePointList.pop_front();
1265 : }
1266 0 : glEnable(GL_MULTISAMPLE);
1267 0 : m_fZStep += Z_STEP;
1268 :
1269 0 : CHECK_GL_ERROR();
1270 :
1271 0 : return 0;
1272 : }
1273 :
1274 0 : void OpenGLRender::SetBackGroundColor(sal_uInt32 color1, sal_uInt32 color2, sal_uInt8 fillStyle)
1275 : {
1276 0 : sal_uInt8 r = (color1 & 0x00FF0000) >> 16;
1277 0 : sal_uInt8 g = (color1 & 0x0000FF00) >> 8;
1278 0 : sal_uInt8 b = (color1 & 0x000000FF);
1279 :
1280 0 : m_BackgroundColor[0] = (float)r / 255.0f;
1281 0 : m_BackgroundColor[1] = (float)g / 255.0f;
1282 0 : m_BackgroundColor[2] = (float)b / 255.0f;
1283 0 : m_BackgroundColor[3] = fillStyle ? 1.0 : 0.0;
1284 :
1285 0 : m_BackgroundColor[4] = (float)r / 255.0f;
1286 0 : m_BackgroundColor[5] = (float)g / 255.0f;
1287 0 : m_BackgroundColor[6] = (float)b / 255.0f;
1288 0 : m_BackgroundColor[7] = fillStyle ? 1.0 : 0.0;
1289 :
1290 0 : r = (color2 & 0x00FF0000) >> 16;
1291 0 : g = (color2 & 0x0000FF00) >> 8;
1292 0 : b = (color2 & 0x000000FF);
1293 :
1294 0 : m_BackgroundColor[8] = (float)r / 255.0f;
1295 0 : m_BackgroundColor[9] = (float)g / 255.0f;
1296 0 : m_BackgroundColor[10] = (float)b / 255.0f;
1297 0 : m_BackgroundColor[11] = fillStyle ? 1.0 : 0.0;
1298 :
1299 0 : m_BackgroundColor[12] = (float)r / 255.0f;
1300 0 : m_BackgroundColor[13] = (float)g / 255.0f;
1301 0 : m_BackgroundColor[14] = (float)b / 255.0f;
1302 0 : m_BackgroundColor[15] = fillStyle ? 1.0 : 0.0;
1303 : SAL_INFO("chart2.opengl", "color1 = " << color1 << ", color2 = " << color2);
1304 :
1305 0 : }
1306 :
1307 0 : void OpenGLRender::SetChartTransparencyGradient(long transparencyGradient)
1308 : {
1309 0 : if (transparencyGradient == 1)
1310 : {
1311 0 : m_BackgroundColor[11] = 0.0;
1312 0 : m_BackgroundColor[15] = 0.0;
1313 : }
1314 0 : }
1315 :
1316 0 : void OpenGLRender::GeneratePieSegment2D(double fInnerRadius, double fOutterRadius, double nAngleStart, double nAngleWidth)
1317 : {
1318 0 : double nAngleStep = 1;
1319 0 : PieSegment2DPointList aPointList;
1320 : // TODO: moggi: GL_TRIANGLE_FAN seems not to work
1321 0 : bool bInnerRadiusNotZero = true; //!rtl::math::approxEqual(0.0, fInnerRadius);
1322 0 : size_t nVectorSize = 3*(nAngleWidth/nAngleStep);
1323 0 : if(bInnerRadiusNotZero)
1324 0 : nVectorSize *= 2;
1325 :
1326 0 : nAngleStart += 90;
1327 0 : aPointList.reserve(nVectorSize);
1328 : // if inner radius = 0 generate a normal pie segment (triangle fan)
1329 : // if inner radius != 0 generate a pie segment - inner pie (triangle strip)
1330 0 : if(!bInnerRadiusNotZero)
1331 : {
1332 0 : aPointList.push_back(0);
1333 0 : aPointList.push_back(0);
1334 0 : aPointList.push_back(m_fZStep);
1335 : }
1336 0 : for(double nAngle = nAngleStart; nAngle <= nAngleStart + nAngleWidth; nAngle += nAngleStep)
1337 : {
1338 0 : float xVal = sin(nAngle/360*2*GL_PI);
1339 0 : float yVal = cos(nAngle/360*2*GL_PI);
1340 0 : aPointList.push_back(fOutterRadius * xVal);
1341 0 : aPointList.push_back(fOutterRadius * yVal);
1342 0 : aPointList.push_back(m_fZStep);
1343 :
1344 0 : if(bInnerRadiusNotZero)
1345 : {
1346 0 : aPointList.push_back(fInnerRadius * xVal);
1347 0 : aPointList.push_back(fInnerRadius * yVal);
1348 0 : aPointList.push_back(m_fZStep);
1349 : }
1350 : }
1351 :
1352 0 : m_PieSegment2DShapePointList.push_back(aPointList);
1353 0 : }
1354 :
1355 0 : int OpenGLRender::RenderPieSegment2DShape(float fSize, float fPosX, float fPosY)
1356 : {
1357 0 : int listNum = m_PieSegment2DShapePointList.size();
1358 0 : PosVecf3 trans = {fPosX/OPENGL_SCALE_VALUE, fPosY/OPENGL_SCALE_VALUE, 0.0f};
1359 0 : PosVecf3 angle = {0.0f, 0.0f, 0.0f};
1360 0 : PosVecf3 scale = {fSize/OPENGL_SCALE_VALUE, fSize/OPENGL_SCALE_VALUE, 1.0f};
1361 0 : MoveModelf(trans, angle, scale);
1362 0 : m_MVP = m_Projection * m_View * m_Model;
1363 :
1364 0 : for (int i = 0; i < listNum; i++)
1365 : {
1366 0 : PieSegment2DPointList &pointList = m_PieSegment2DShapePointList.back();
1367 : //fill vertex buffer
1368 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
1369 0 : glBufferData(GL_ARRAY_BUFFER, pointList.size() * sizeof(float), &pointList[0] , GL_STATIC_DRAW);
1370 : // Use our shader
1371 0 : glUseProgram(m_CommonProID);
1372 :
1373 0 : glUniform4fv(m_2DColorID, 1, &m_2DColor[0]);
1374 :
1375 0 : glUniformMatrix4fv(m_MatrixID, 1, GL_FALSE, &m_MVP[0][0]);
1376 :
1377 : // 1rst attribute buffer : vertices
1378 0 : glEnableVertexAttribArray(m_2DVertexID);
1379 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
1380 : glVertexAttribPointer(
1381 : m_2DVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
1382 : 3, // size
1383 : GL_FLOAT, // type
1384 : GL_FALSE, // normalized?
1385 : 0, // stride
1386 : (void*)0 // array buffer offset
1387 0 : );
1388 0 : glDrawArrays(GL_TRIANGLE_STRIP, 0, pointList.size() / 3); // 12*3 indices starting at 0 -> 12 triangles
1389 0 : glDisableVertexAttribArray(m_2DVertexID);
1390 0 : glUseProgram(0);
1391 0 : m_PieSegment2DShapePointList.pop_back();
1392 0 : CHECK_GL_ERROR();
1393 :
1394 : }
1395 0 : m_fZStep += Z_STEP;
1396 :
1397 0 : CHECK_GL_ERROR();
1398 0 : return 0;
1399 : }
1400 :
1401 0 : int OpenGLRender::RenderSymbol2DShape(float x, float y, float , float , sal_Int32 nSymbol)
1402 : {
1403 0 : CHECK_GL_ERROR();
1404 :
1405 0 : glPointSize(20.f);
1406 0 : CHECK_GL_ERROR();
1407 0 : PosVecf3 trans = {0.0, 0.0, 0.0};
1408 0 : PosVecf3 angle = {0.0f, 0.0f, 0.0f};
1409 0 : PosVecf3 scale = {1.0, 1.0, 1.0f};
1410 0 : MoveModelf(trans, angle, scale);
1411 0 : m_MVP = m_Projection * m_View * m_Model;
1412 :
1413 0 : float aPos[3] = { x/OPENGL_SCALE_VALUE, y/OPENGL_SCALE_VALUE, m_fZStep };
1414 : //fill vertex buffer
1415 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
1416 0 : CHECK_GL_ERROR();
1417 0 : glBufferData(GL_ARRAY_BUFFER, 3 * sizeof(float), aPos, GL_STATIC_DRAW);
1418 0 : CHECK_GL_ERROR();
1419 :
1420 : // Use our shader
1421 0 : glUseProgram(m_SymbolProID);
1422 0 : CHECK_GL_ERROR();
1423 :
1424 0 : glUniform4fv(m_SymbolColorID, 1, &m_2DColor[0]);
1425 0 : glUniform1i(m_SymbolShapeID, nSymbol);
1426 0 : CHECK_GL_ERROR();
1427 :
1428 0 : glUniformMatrix4fv(m_SymbolMatrixID, 1, GL_FALSE, &m_MVP[0][0]);
1429 :
1430 0 : CHECK_GL_ERROR();
1431 : // 1rst attribute buffer : vertices
1432 0 : glEnableVertexAttribArray(m_SymbolVertexID);
1433 0 : glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
1434 : glVertexAttribPointer(
1435 : m_SymbolVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
1436 : 3, // size
1437 : GL_FLOAT, // type
1438 : GL_FALSE, // normalized?
1439 : 0, // stride
1440 : (void*)0 // array buffer offset
1441 0 : );
1442 :
1443 0 : glDrawArrays(GL_POINTS, 0, 1);
1444 :
1445 0 : glDisableVertexAttribArray(m_SymbolVertexID);
1446 0 : CHECK_GL_ERROR();
1447 0 : glUseProgram(0);
1448 0 : m_fZStep += Z_STEP;
1449 :
1450 0 : CHECK_GL_ERROR();
1451 0 : return 0;
1452 0 : }
1453 :
1454 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|