1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     demo_GraphicsDrawing.cpp
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 46365 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "demo/Render/demo_GraphicsDrawing.h"
17 
18 namespace demo
19 {
20 
21     /* ------------------------------------------------------------------------
22         GraphicsDrawing class  member function
23     ------------------------------------------------------------------------ */
24 
GraphicsDrawing(void)25     GraphicsDrawing::GraphicsDrawing(void) :
26     m_Depth(1.0f), m_AutoDepth(true),
27     m_ShaderManager(),
28     m_InitializeTriangles(false), m_InitializeSquares(false),
29     m_InitializeTexts(false),
30     m_MaxTrianglesNum(demo::MAX_TRIANGLES_NUM), m_TotalTrianglesNum(0),
31     m_MaxSquaresNum(demo::MAX_SQUARES_NUM), m_TotalSquaresNum(0),
32     m_MaxTextLength(demo::MAX_TEXT_LENGTH), m_TotalTextLength(0),
33     m_UseColorFillProgram(false), m_UseFontProgram(false),
34     m_PointSize(1.0f), m_LineWidth(1.0f),
35     m_FontSize(1.0f)
36     {
37         SetWindowSize(NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT);
38     }
39 
~GraphicsDrawing(void)40     GraphicsDrawing::~GraphicsDrawing(void)
41     {
42         Finalize();
43     }
44 
Initialize(void)45     void GraphicsDrawing::Initialize(void)
46     {
47         m_InitializeTriangles = false;
48         m_InitializeSquares = false;
49         m_InitializeTexts = false;
50 
51         m_UseColorFillProgram = false;
52         m_UseFontProgram = false;
53 
54         m_Color[0] = 1.0f;
55         m_Color[1] = 0.0f;
56         m_Color[2] = 0.0f;
57         m_Color[3] = 1.0f;
58 
59         m_Depth = 1.0f;
60         m_AutoDepth = true;
61         m_DepthValue = 0.0001f;
62 
63         DecrementDepth();
64 
65         m_PointSize = 1.0f;
66         m_LineWidth = 1.0f;
67         m_FontSize = 8.0f;
68 
69         bool flag = m_ShaderManager.Initialize();
70         if (! flag )
71         {
72             NN_TPANIC_("GraphicsDrawing::Initialize() : ShaderManager.Initialize() failed.\n");
73         }
74     }
75 
Finalize(void)76     void GraphicsDrawing::Finalize(void)
77     {
78         DEMO_ASSERT_GL_ERROR();
79 
80         m_ShaderManager.Finalize();
81 
82         m_TrianglesRenderData.Finalize();
83         m_SquaresRenderData.Finalize();
84         m_TextsRenderData.Finalize();
85 
86         m_InitializeTriangles = false;
87         m_InitializeSquares = false;
88         m_InitializeTexts = false;
89 
90         DEMO_ASSERT_GL_ERROR();
91     }
92 
InitializeTriangles(const u32 maxTrianglesNum)93     void GraphicsDrawing::InitializeTriangles(const u32 maxTrianglesNum)
94     {
95         if ( m_InitializeTriangles )
96         {
97             return;
98         }
99 
100         DEMO_ASSERT_GL_ERROR();
101 
102         m_TrianglesRenderData.Initialize();
103 
104         u32 vertexAttributes = m_ShaderManager.GetVertexAttributes(demo::COLOR_FILL_SHADER);
105 
106         m_MaxTrianglesNum = maxTrianglesNum;
107         u32 maxVerticesNum = 3 * maxTrianglesNum;
108         m_TrianglesRenderData.InitializeVertexBuffers(vertexAttributes,
109             GL_TRIANGLES, maxVerticesNum, m_MaxTrianglesNum);
110         m_TotalTrianglesNum = 0;
111 
112         m_InitializeTriangles = true;
113 
114         DEMO_ASSERT_GL_ERROR();
115     }
116 
InitializeSquares(const u32 maxSquaresNum)117     void GraphicsDrawing::InitializeSquares(const u32 maxSquaresNum)
118     {
119         if ( m_InitializeSquares )
120         {
121             return;
122         }
123 
124         DEMO_ASSERT_GL_ERROR();
125 
126         m_SquaresRenderData.Initialize();
127 
128         u32 vertexAttributes = m_ShaderManager.GetVertexAttributes(demo::COLOR_FILL_SHADER);
129 
130         m_MaxSquaresNum = maxSquaresNum;
131         u32 maxVerticesNum = m_MaxSquaresNum * 4;
132         u32 maxTrianglesNum = m_MaxSquaresNum * 6;
133         m_SquaresRenderData.InitializeVertexBuffers(vertexAttributes,
134             GL_TRIANGLE_STRIP, maxVerticesNum, maxTrianglesNum);
135         m_TotalSquaresNum = 0;
136 
137         m_InitializeSquares = true;
138 
139         DEMO_ASSERT_GL_ERROR();
140     }
141 
InitializeTexts(const u32 maxLength)142     void GraphicsDrawing::InitializeTexts(const u32 maxLength)
143     {
144         if ( m_InitializeTexts )
145         {
146             return;
147         }
148 
149         DEMO_ASSERT_GL_ERROR();
150 
151         m_TextsRenderData.Initialize();
152 
153         u32 vertexAttributes = m_ShaderManager.GetVertexAttributes(demo::FONT_SHADER);
154 
155         m_MaxTextLength = maxLength;
156         m_TextsRenderData.InitializeVertexBuffers(vertexAttributes, GL_TRIANGLES, m_MaxTextLength);
157         m_TotalTextLength = 0;
158 
159         m_InitializeTexts = true;
160 
161         DEMO_ASSERT_GL_ERROR();
162     }
163 
SetWindowSize(const f32 windowWidth,const f32 windowHeight)164     void GraphicsDrawing::SetWindowSize(const f32 windowWidth, const f32 windowHeight)
165     {
166         m_WindowWidth = windowWidth;
167         m_WindowHeight = windowHeight;
168 
169         m_TrianglesRenderData.SetWindowSize(m_WindowWidth, m_WindowHeight);
170         m_SquaresRenderData.SetWindowSize(m_WindowWidth, m_WindowHeight);
171         m_TextsRenderData.SetWindowSize(m_WindowWidth, m_WindowHeight);
172     }
173 
GetWindowSize(f32 & windowWidth,f32 & windowHeight)174     void GraphicsDrawing::GetWindowSize(f32& windowWidth, f32& windowHeight)
175     {
176         windowWidth = m_WindowWidth;
177         windowHeight = m_WindowHeight;
178     }
179 
SetColor(const f32 red,const f32 green,const f32 blue)180     void GraphicsDrawing::SetColor(const f32 red, const f32 green, const f32 blue)
181     {
182         m_Color[0] = red;
183         m_Color[1] = green;
184         m_Color[2] = blue;
185         m_Color[3] = 1.0f;
186     }
187 
SetColor(const f32 red,const f32 green,const f32 blue,const f32 alpha)188     void GraphicsDrawing::SetColor(const f32 red, const f32 green, const f32 blue, const f32 alpha)
189     {
190         m_Color[0] = red;
191         m_Color[1] = green;
192         m_Color[2] = blue;
193         m_Color[3] = alpha;
194     }
195 
SetDepth(const f32 depth)196     void GraphicsDrawing::SetDepth(const f32 depth)
197     {
198         m_Depth = depth;
199     }
200 
SetAutoDepth(const bool enableAutoDepth)201     void GraphicsDrawing::SetAutoDepth(const bool enableAutoDepth)
202     {
203         m_AutoDepth = enableAutoDepth;
204     }
205 
DecrementDepth(void)206     void GraphicsDrawing::DecrementDepth(void)
207     {
208         if ( m_AutoDepth )
209         {
210             m_Depth -= m_DepthValue;
211         }
212 
213         if ( m_Depth <= 0.0f )
214         {
215             m_Depth = 0.0f;
216         }
217     }
218 
SetPointSize(const f32 pointSize)219     void GraphicsDrawing::SetPointSize(const f32 pointSize)
220     {
221         m_PointSize = pointSize;
222     }
223 
DrawPoint(const f32 windowCoordinateX,const f32 windowCoordinateY)224     void GraphicsDrawing::DrawPoint(const f32 windowCoordinateX, const f32 windowCoordinateY)
225     {
226         f32 pointHalfSize = 0.5f * m_PointSize;
227 
228         f32 windowCoordinateX0 = windowCoordinateX - pointHalfSize;
229         f32 windowCoordinateX1 = windowCoordinateX + pointHalfSize;
230         f32 windowCoordinateY0 = windowCoordinateY - pointHalfSize;
231         f32 windowCoordinateY1 = windowCoordinateY + pointHalfSize;
232 
233         FillSquare(windowCoordinateX0, windowCoordinateY0,
234             windowCoordinateX0, windowCoordinateY1,
235             windowCoordinateX1, windowCoordinateY1,
236             windowCoordinateX1, windowCoordinateY0);
237     }
238 
SetLineWidth(const f32 lineWidth)239     void GraphicsDrawing::SetLineWidth(const f32 lineWidth)
240     {
241         m_LineWidth = lineWidth;
242     }
243 
DrawLine(const f32 windowCoordinateX0,const f32 windowCoordinateY0,const f32 windowCoordinateX1,const f32 windowCoordinateY1)244     void GraphicsDrawing::DrawLine(const f32 windowCoordinateX0, const f32 windowCoordinateY0,
245                                      const f32 windowCoordinateX1, const f32 windowCoordinateY1)
246     {
247         static const f32 DEMO_MATH_ERROR = 0.00001f;
248 
249         f32 s_LineHalfWidth = 0.5f * m_LineWidth;
250 
251         f32 x01 = windowCoordinateX1 - windowCoordinateX0;
252         f32 y01 = windowCoordinateY1 - windowCoordinateY0;
253 
254         f32 gradientX = 0.0f;
255         f32 gradientY = 0.0f;
256 
257         if ( nn::math::FAbs(x01) < DEMO_MATH_ERROR )
258         {
259             gradientX = 1.0f;
260         }
261         else if ( nn::math::FAbs(y01) < DEMO_MATH_ERROR )
262         {
263             gradientY = 1.0f;
264         }
265         else
266         {
267             gradientX = y01;
268             gradientY = (- x01);
269 
270             f32 gradient = gradientX * gradientX + gradientY * gradientY;
271             gradient = nn::math::FSqrt(gradient);
272 
273             gradientX /= gradient;
274             gradientY /= gradient;
275         }
276 
277         gradientX *= s_LineHalfWidth;
278         gradientY *= s_LineHalfWidth;
279 
280         FillSquare(windowCoordinateX0 + gradientX, windowCoordinateY0 + gradientY,
281             windowCoordinateX0 - gradientX, windowCoordinateY0 - gradientY,
282             windowCoordinateX1 - gradientX, windowCoordinateY1 - gradientY,
283             windowCoordinateX1 + gradientX, windowCoordinateY1 + gradientY);
284 
285         DEMO_ASSERT_GL_ERROR();
286     }
287 
FillSquare(const f32 windowCoordinateX0,const f32 windowCoordinateY0,const f32 windowCoordinateX1,const f32 windowCoordinateY1,const f32 windowCoordinateX2,const f32 windowCoordinateY2,const f32 windowCoordinateX3,const f32 windowCoordinateY3)288     void GraphicsDrawing::FillSquare(const f32 windowCoordinateX0, const f32 windowCoordinateY0,
289                                      const f32 windowCoordinateX1, const f32 windowCoordinateY1,
290                                      const f32 windowCoordinateX2, const f32 windowCoordinateY2,
291                                      const f32 windowCoordinateX3, const f32 windowCoordinateY3)
292     {
293         if (! m_InitializeSquares )
294         {
295             InitializeSquares();
296         }
297 
298         if ( m_TotalSquaresNum >= m_MaxSquaresNum )
299         {
300             NN_TLOG_("GraphicsDrawing::FillSquare() maxSquares limit\n");
301             NN_TLOG_("  squaresIndex = %d, maxSquaresNum = %d\n", m_TotalSquaresNum, m_MaxSquaresNum);
302             return;
303         }
304 
305         m_UseColorFillProgram = true;
306 
307         demo::TrianglesRenderData& renderData = m_SquaresRenderData;
308         u32 vertexIndex = renderData.GetPackedVerticesNum();
309         u32 squareIndex = renderData.GetPackedTrianglesNum() / 4;
310 
311         // POSITION 0
312         f32 normalizedDeviceCoordinateX = 0.0f;
313         f32 normalizedDeviceCoordinateY = 0.0f;
314         renderData.GetNormalizedDeviceCoordinateXY(windowCoordinateX0, windowCoordinateY0,
315             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY);
316         renderData.SetPosition(vertexIndex,
317             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY, m_Depth, 1.0f);
318 
319         // POSITION 1
320         renderData.GetNormalizedDeviceCoordinateXY(windowCoordinateX1, windowCoordinateY1,
321             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY);
322         renderData.SetPosition(vertexIndex + 2,
323             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY, m_Depth, 1.0f);
324 
325         // POSITION 2
326         renderData.GetNormalizedDeviceCoordinateXY(windowCoordinateX2, windowCoordinateY2,
327             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY);
328         renderData.SetPosition(vertexIndex + 3,
329             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY, m_Depth, 1.0f);
330 
331         // POSITION 3
332         renderData.GetNormalizedDeviceCoordinateXY(windowCoordinateX3, windowCoordinateY3,
333             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY);
334         renderData.SetPosition(vertexIndex + 1,
335             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY, m_Depth, 1.0f);
336 
337         DecrementDepth();
338 
339         // COLOR
340         for (u32 i = 0; i < 4; i++)
341         {
342             renderData.SetColor(vertexIndex + i,
343                 m_Color[0], m_Color[1], m_Color[2]);
344         }
345 
346         // INDEX
347         renderData.SetSquareIndex(squareIndex,
348             vertexIndex, vertexIndex + 1, vertexIndex + 2, vertexIndex + 3);
349 
350         renderData.AddPackedVerticesNum(4);
351         renderData.AddPackedTrianglesNum(4);
352 
353         m_TotalSquaresNum += 1;
354 
355         DEMO_ASSERT_GL_ERROR();
356     }
357 
FillRectangle(const f32 windowCoordinateX,const f32 windowCoordinateY,const f32 width,const f32 height)358     void GraphicsDrawing::FillRectangle(const f32 windowCoordinateX,
359                                         const f32 windowCoordinateY,
360                                         const f32 width, const f32 height)
361     {
362         f32 windowCoordinateX1 = windowCoordinateX + width;
363         f32 windowCoordinateY1 = windowCoordinateY + height;
364 
365         FillTriangle(windowCoordinateX, windowCoordinateY,
366             windowCoordinateX, windowCoordinateY1,
367             windowCoordinateX1, windowCoordinateY);
368 
369         FillTriangle(windowCoordinateX, windowCoordinateY1,
370             windowCoordinateX1, windowCoordinateY1,
371             windowCoordinateX1, windowCoordinateY);
372 
373         DEMO_ASSERT_GL_ERROR();
374     }
375 
FillTriangle(const f32 windowCoordinateX0,const f32 windowCoordinateY0,const f32 windowCoordinateX1,const f32 windowCoordinateY1,const f32 windowCoordinateX2,const f32 windowCoordinateY2)376     void GraphicsDrawing::FillTriangle(const f32 windowCoordinateX0, const f32 windowCoordinateY0,
377                                        const f32 windowCoordinateX1, const f32 windowCoordinateY1,
378                                        const f32 windowCoordinateX2, const f32 windowCoordinateY2)
379     {
380         if (! m_InitializeTriangles )
381         {
382             InitializeTriangles();
383         }
384 
385         if ( m_TotalTrianglesNum >= m_MaxTrianglesNum )
386         {
387             NN_TLOG_("GraphicsDrawing::FillTriangle() maxSquares limit\n");
388             NN_TLOG_("  trianglesIndex = %d, maxTrianglesNum = %d\n", m_TotalTrianglesNum, m_MaxTrianglesNum);
389             return;
390         }
391 
392         m_UseColorFillProgram = true;
393         demo::TrianglesRenderData& renderData = m_TrianglesRenderData;
394         u32 triangleIndex = renderData.GetPackedTrianglesNum();
395 
396         // POSITION 0
397         f32 normalizedDeviceCoordinateX = 0.0f;
398         f32 normalizedDeviceCoordinateY = 0.0f;
399         renderData.GetNormalizedDeviceCoordinateXY(windowCoordinateX0, windowCoordinateY0,
400             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY);
401         renderData.SetPosition(3 * triangleIndex,
402             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY, m_Depth, 1.0f);
403 
404         // POSITION 1
405         renderData.GetNormalizedDeviceCoordinateXY(windowCoordinateX1, windowCoordinateY1,
406             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY);
407         renderData.SetPosition(3 * triangleIndex + 1,
408             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY, m_Depth, 1.0f);
409 
410         // POSITION 2
411         renderData.GetNormalizedDeviceCoordinateXY(windowCoordinateX2, windowCoordinateY2,
412             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY);
413         renderData.SetPosition(3 * triangleIndex + 2,
414             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY, m_Depth, 1.0f);
415 
416         DecrementDepth();
417 
418         // COLOR
419         for (u32 i = 0; i < 3; i++)
420         {
421             renderData.SetColor(3 * triangleIndex + i,
422                 m_Color[0], m_Color[1], m_Color[2]);
423         }
424 
425         // INDEX
426         renderData.SetIndex(triangleIndex,
427                 3 * triangleIndex, 3 * triangleIndex + 1, 3 * triangleIndex + 2);
428 
429         renderData.AddPackedVerticesNum(3);
430         renderData.AddPackedTrianglesNum(1);
431 
432         m_TotalTrianglesNum += 1;
433 
434         DEMO_ASSERT_GL_ERROR();
435     }
436 
SetFontSize(const f32 fontSize)437     void GraphicsDrawing::SetFontSize(const f32 fontSize)
438     {
439         m_FontSize = fontSize;
440         m_TextsRenderData.SetFontSize(m_FontSize);
441     }
442 
DrawText(const f32 windowCoordinateX,const f32 windowCoordinateY,const char * format,...)443     void GraphicsDrawing::DrawText(const f32 windowCoordinateX, const f32 windowCoordinateY,
444                                    const char* format, ...)
445     {
446         static const u32 tmpBufferSize = 1024;
447         static char textBuffer[tmpBufferSize];
448 
449         if (! m_InitializeTexts )
450         {
451             InitializeTexts();
452         }
453 
454         va_list va;
455         va_start(va, format);
456         vsnprintf(textBuffer, tmpBufferSize, format, va);
457         va_end(va);
458 
459         DrawTextBuffer(windowCoordinateX, windowCoordinateY, textBuffer);
460 
461         DEMO_ASSERT_GL_ERROR();
462     }
463 
DrawTextBuffer(const f32 windowCoordinateX,const f32 windowCoordinateY,const char * textBuffer)464      void GraphicsDrawing::DrawTextBuffer(const f32 windowCoordinateX, const f32 windowCoordinateY,
465          const char* textBuffer)
466     {
467         if (! m_InitializeTexts )
468         {
469             InitializeTexts();
470         }
471 
472         char* ch_ptr = const_cast<char*>(textBuffer);
473         u32 textLength = 0;
474         for (u32 i = 0; i < demo::MAX_CHAR_LENGTH_PER_LINE; i++)
475         {
476             char c = (*ch_ptr);
477             if ( c == '\0')
478             {
479                break;
480             }
481 
482             if ( (0x20 <= c) && (c <= 0x7f) )
483             {
484                textLength += 1;
485                ch_ptr++;
486             }
487             else
488             {
489                 break;
490             }
491         }
492 
493         demo::TextsRenderData& renderData = m_TextsRenderData;
494         if ( (m_TotalTextLength + textLength) >= m_MaxTextLength )
495         {
496             NN_TLOG_("GraphicsDrawing::DrawText() maxText limit\n");
497             NN_TLOG_("  textLength = %d, maxTextLength = %d, totalTextLength = %d\n",
498                 textLength, m_MaxTextLength, m_TotalTextLength);
499             return;
500         }
501 
502         m_UseFontProgram = true;
503 
504         m_TextsRenderData.SetFontColor(m_Color[0], m_Color[1], m_Color[2], m_Color[3]);
505         renderData.AddText(windowCoordinateX, windowCoordinateY,
506             textBuffer, textLength, m_Depth);
507 
508         m_TotalTextLength += textLength;
509 
510         DecrementDepth();
511 
512         DEMO_ASSERT_GL_ERROR();
513     }
514 
Flush(void)515     void GraphicsDrawing::Flush(void)
516     {
517         FlushColorFillPrimitives();
518         FlushTexts();
519 
520         m_Depth = 1.0f;
521         DecrementDepth();
522     }
523 
FlushColorFillPrimitives(void)524     void GraphicsDrawing::FlushColorFillPrimitives(void)
525     {
526         if (! m_UseColorFillProgram )
527         {
528             return;
529         }
530 
531         demo::ProgramObject* shaderProgramPtr = m_ShaderManager.GetShaderProgram(demo::COLOR_FILL_SHADER);
532         shaderProgramPtr->SetUse3d(false);
533         shaderProgramPtr->Begin();
534         shaderProgramPtr->Use();
535 
536         m_TrianglesRenderData.DrawPackedTriangles();
537         m_SquaresRenderData.DrawPackedTriangles();
538 
539         m_TotalTrianglesNum = 0;
540         m_TotalSquaresNum = 0;
541 
542         shaderProgramPtr->End();
543 
544         m_UseColorFillProgram = false;
545 
546         DEMO_ASSERT_GL_ERROR();
547     }
548 
FlushTexts(void)549     void GraphicsDrawing::FlushTexts(void)
550     {
551         if (! m_UseFontProgram )
552         {
553             return;
554         }
555 
556         demo::ProgramObject* shaderProgramPtr = m_ShaderManager.GetShaderProgram(demo::FONT_SHADER);
557         shaderProgramPtr->SetUse3d(false);
558         shaderProgramPtr->Begin();
559         shaderProgramPtr->Use();
560 
561         m_TextsRenderData.DrawPackedTriangles();
562         m_TextsRenderData.ClearPackedTextLength();
563         m_TotalTextLength = 0;
564 
565         shaderProgramPtr->End();
566 
567         m_UseFontProgram = false;
568 
569         DEMO_ASSERT_GL_ERROR();
570     }
571 
572 }
573