| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE examples.
 -    Copyright (c) 2017 - ROLI Ltd.
 - 
 -    The code included in this file is provided under the terms of the ISC license
 -    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
 -    To use, copy, modify, and/or distribute this software for any purpose with or
 -    without fee is hereby granted provided that the above copyright notice and
 -    this permission notice appear in all copies.
 - 
 -    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES,
 -    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR
 -    PURPOSE, ARE DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - /*******************************************************************************
 -  The block below describes the properties of this PIP. A PIP is a short snippet
 -  of code that can be read by the Projucer and used to generate a JUCE project.
 - 
 -  BEGIN_JUCE_PIP_METADATA
 - 
 -  name:             OpenGLAppDemo
 -  version:          1.0.0
 -  vendor:           JUCE
 -  website:          http://juce.com
 -  description:      Simple OpenGL application.
 - 
 -  dependencies:     juce_core, juce_data_structures, juce_events, juce_graphics,
 -                    juce_gui_basics, juce_gui_extra, juce_opengl
 -  exporters:        xcode_mac, vs2019, xcode_iphone
 - 
 -  moduleFlags:      JUCE_STRICT_REFCOUNTEDPOINTER=1
 - 
 -  type:             Component
 -  mainClass:        OpenGLAppDemo
 - 
 -  useLocalCopy:     1
 - 
 -  END_JUCE_PIP_METADATA
 - 
 - *******************************************************************************/
 - 
 - #pragma once
 - 
 - #include "../Assets/DemoUtilities.h"
 - #include "../Assets/WavefrontObjParser.h"
 - 
 - //==============================================================================
 - /*
 -     This component lives inside our window, and this is where you should put all
 -     your controls and content.
 - */
 - class OpenGLAppDemo   : public OpenGLAppComponent
 - {
 - public:
 -     //==============================================================================
 -     OpenGLAppDemo()
 -     {
 -         setSize (800, 600);
 -     }
 - 
 -     ~OpenGLAppDemo() override
 -     {
 -         shutdownOpenGL();
 -     }
 - 
 -     void initialise() override
 -     {
 -         createShaders();
 -     }
 - 
 -     void shutdown() override
 -     {
 -         shader    .reset();
 -         shape     .reset();
 -         attributes.reset();
 -         uniforms  .reset();
 -     }
 - 
 -     Matrix3D<float> getProjectionMatrix() const
 -     {
 -         auto w = 1.0f / (0.5f + 0.1f);
 -         auto h = w * getLocalBounds().toFloat().getAspectRatio (false);
 - 
 -         return Matrix3D<float>::fromFrustum (-w, w, -h, h, 4.0f, 30.0f);
 -     }
 - 
 -     Matrix3D<float> getViewMatrix() const
 -     {
 -         Matrix3D<float> viewMatrix ({ 0.0f, 0.0f, -10.0f });
 -         Matrix3D<float> rotationMatrix = viewMatrix.rotation ({ -0.3f, 5.0f * std::sin (getFrameCounter() * 0.01f), 0.0f });
 - 
 -         return rotationMatrix * viewMatrix;
 -     }
 - 
 -     void render() override
 -     {
 -         jassert (OpenGLHelpers::isContextActive());
 - 
 -         auto desktopScale = (float) openGLContext.getRenderingScale();
 -         OpenGLHelpers::clear (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
 - 
 -         glEnable (GL_BLEND);
 -         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 - 
 -         glViewport (0, 0, roundToInt (desktopScale * getWidth()), roundToInt (desktopScale * getHeight()));
 - 
 -         shader->use();
 - 
 -         if (uniforms->projectionMatrix.get() != nullptr)
 -             uniforms->projectionMatrix->setMatrix4 (getProjectionMatrix().mat, 1, false);
 - 
 -         if (uniforms->viewMatrix.get() != nullptr)
 -             uniforms->viewMatrix->setMatrix4 (getViewMatrix().mat, 1, false);
 - 
 -         shape->draw (openGLContext, *attributes);
 - 
 -         // Reset the element buffers so child Components draw correctly
 -         openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, 0);
 -         openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
 - 
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         // You can add your component specific drawing code here!
 -         // This will draw over the top of the openGL background.
 - 
 -         g.setColour (getLookAndFeel().findColour (Label::textColourId));
 -         g.setFont (20);
 -         g.drawText ("OpenGL Example", 25, 20, 300, 30, Justification::left);
 -         g.drawLine (20, 20, 170, 20);
 -         g.drawLine (20, 50, 170, 50);
 -     }
 - 
 -     void resized() override
 -     {
 -         // This is called when this component is resized.
 -         // If you add any child components, this is where you should
 -         // update their positions.
 -     }
 - 
 -     void createShaders()
 -     {
 -         vertexShader =
 -             "attribute vec4 position;\n"
 -             "attribute vec4 sourceColour;\n"
 -             "attribute vec2 textureCoordIn;\n"
 -             "\n"
 -             "uniform mat4 projectionMatrix;\n"
 -             "uniform mat4 viewMatrix;\n"
 -             "\n"
 -             "varying vec4 destinationColour;\n"
 -             "varying vec2 textureCoordOut;\n"
 -             "\n"
 -             "void main()\n"
 -             "{\n"
 -             "    destinationColour = sourceColour;\n"
 -             "    textureCoordOut = textureCoordIn;\n"
 -             "    gl_Position = projectionMatrix * viewMatrix * position;\n"
 -             "}\n";
 - 
 -         fragmentShader =
 -            #if JUCE_OPENGL_ES
 -             "varying lowp vec4 destinationColour;\n"
 -             "varying lowp vec2 textureCoordOut;\n"
 -            #else
 -             "varying vec4 destinationColour;\n"
 -             "varying vec2 textureCoordOut;\n"
 -            #endif
 -             "\n"
 -             "void main()\n"
 -             "{\n"
 -            #if JUCE_OPENGL_ES
 -             "    lowp vec4 colour = vec4(0.95, 0.57, 0.03, 0.7);\n"
 -            #else
 -             "    vec4 colour = vec4(0.95, 0.57, 0.03, 0.7);\n"
 -            #endif
 -             "    gl_FragColor = colour;\n"
 -             "}\n";
 - 
 -         std::unique_ptr<OpenGLShaderProgram> newShader (new OpenGLShaderProgram (openGLContext));
 -         String statusText;
 - 
 -         if (newShader->addVertexShader (OpenGLHelpers::translateVertexShaderToV3 (vertexShader))
 -               && newShader->addFragmentShader (OpenGLHelpers::translateFragmentShaderToV3 (fragmentShader))
 -               && newShader->link())
 -         {
 -             shape     .reset();
 -             attributes.reset();
 -             uniforms  .reset();
 - 
 -             shader.reset (newShader.release());
 -             shader->use();
 - 
 -             shape     .reset (new Shape (openGLContext));
 -             attributes.reset (new Attributes (openGLContext, *shader));
 -             uniforms  .reset (new Uniforms (openGLContext, *shader));
 - 
 -             statusText = "GLSL: v" + String (OpenGLShaderProgram::getLanguageVersion(), 2);
 -         }
 -         else
 -         {
 -             statusText = newShader->getLastError();
 -         }
 -     }
 - 
 - 
 - private:
 -     //==============================================================================
 -     struct Vertex
 -     {
 -         float position[3];
 -         float normal[3];
 -         float colour[4];
 -         float texCoord[2];
 -     };
 - 
 -     //==============================================================================
 -     // This class just manages the attributes that the shaders use.
 -     struct Attributes
 -     {
 -         Attributes (OpenGLContext& openGLContext, OpenGLShaderProgram& shaderProgram)
 -         {
 -             position      .reset (createAttribute (openGLContext, shaderProgram, "position"));
 -             normal        .reset (createAttribute (openGLContext, shaderProgram, "normal"));
 -             sourceColour  .reset (createAttribute (openGLContext, shaderProgram, "sourceColour"));
 -             textureCoordIn.reset (createAttribute (openGLContext, shaderProgram, "textureCoordIn"));
 -         }
 - 
 -         void enable (OpenGLContext& glContext)
 -         {
 -             if (position.get() != nullptr)
 -             {
 -                 glContext.extensions.glVertexAttribPointer (position->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), nullptr);
 -                 glContext.extensions.glEnableVertexAttribArray (position->attributeID);
 -             }
 - 
 -             if (normal.get() != nullptr)
 -             {
 -                 glContext.extensions.glVertexAttribPointer (normal->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 3));
 -                 glContext.extensions.glEnableVertexAttribArray (normal->attributeID);
 -             }
 - 
 -             if (sourceColour.get() != nullptr)
 -             {
 -                 glContext.extensions.glVertexAttribPointer (sourceColour->attributeID, 4, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 6));
 -                 glContext.extensions.glEnableVertexAttribArray (sourceColour->attributeID);
 -             }
 - 
 -             if (textureCoordIn.get() != nullptr)
 -             {
 -                 glContext.extensions.glVertexAttribPointer (textureCoordIn->attributeID, 2, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 10));
 -                 glContext.extensions.glEnableVertexAttribArray (textureCoordIn->attributeID);
 -             }
 -         }
 - 
 -         void disable (OpenGLContext& glContext)
 -         {
 -             if (position.get() != nullptr)       glContext.extensions.glDisableVertexAttribArray (position->attributeID);
 -             if (normal.get() != nullptr)         glContext.extensions.glDisableVertexAttribArray (normal->attributeID);
 -             if (sourceColour.get() != nullptr)   glContext.extensions.glDisableVertexAttribArray (sourceColour->attributeID);
 -             if (textureCoordIn.get() != nullptr) glContext.extensions.glDisableVertexAttribArray (textureCoordIn->attributeID);
 -         }
 - 
 -         std::unique_ptr<OpenGLShaderProgram::Attribute> position, normal, sourceColour, textureCoordIn;
 - 
 -     private:
 -         static OpenGLShaderProgram::Attribute* createAttribute (OpenGLContext& openGLContext,
 -                                                                 OpenGLShaderProgram& shader,
 -                                                                 const char* attributeName)
 -         {
 -             if (openGLContext.extensions.glGetAttribLocation (shader.getProgramID(), attributeName) < 0)
 -                 return nullptr;
 - 
 -             return new OpenGLShaderProgram::Attribute (shader, attributeName);
 -         }
 -     };
 - 
 -     //==============================================================================
 -     // This class just manages the uniform values that the demo shaders use.
 -     struct Uniforms
 -     {
 -         Uniforms (OpenGLContext& openGLContext, OpenGLShaderProgram& shaderProgram)
 -         {
 -             projectionMatrix.reset (createUniform (openGLContext, shaderProgram, "projectionMatrix"));
 -             viewMatrix      .reset (createUniform (openGLContext, shaderProgram, "viewMatrix"));
 -         }
 - 
 -         std::unique_ptr<OpenGLShaderProgram::Uniform> projectionMatrix, viewMatrix;
 - 
 -     private:
 -         static OpenGLShaderProgram::Uniform* createUniform (OpenGLContext& openGLContext,
 -                                                             OpenGLShaderProgram& shaderProgram,
 -                                                             const char* uniformName)
 -         {
 -             if (openGLContext.extensions.glGetUniformLocation (shaderProgram.getProgramID(), uniformName) < 0)
 -                 return nullptr;
 - 
 -             return new OpenGLShaderProgram::Uniform (shaderProgram, uniformName);
 -         }
 -     };
 - 
 -     //==============================================================================
 -     /** This loads a 3D model from an OBJ file and converts it into some vertex buffers
 -         that we can draw.
 -     */
 -     struct Shape
 -     {
 -         Shape (OpenGLContext& glContext)
 -         {
 -             if (shapeFile.load (loadEntireAssetIntoString ("teapot.obj")).wasOk())
 -                 for (auto* shapeVertices : shapeFile.shapes)
 -                     vertexBuffers.add (new VertexBuffer (glContext, *shapeVertices));
 -         }
 - 
 -         void draw (OpenGLContext& glContext, Attributes& glAttributes)
 -         {
 -             for (auto* vertexBuffer : vertexBuffers)
 -             {
 -                 vertexBuffer->bind();
 - 
 -                 glAttributes.enable (glContext);
 -                 glDrawElements (GL_TRIANGLES, vertexBuffer->numIndices, GL_UNSIGNED_INT, nullptr);
 -                 glAttributes.disable (glContext);
 -             }
 -         }
 - 
 -     private:
 -         struct VertexBuffer
 -         {
 -             VertexBuffer (OpenGLContext& context, WavefrontObjFile::Shape& aShape) : openGLContext (context)
 -             {
 -                 numIndices = aShape.mesh.indices.size();
 - 
 -                 openGLContext.extensions.glGenBuffers (1, &vertexBuffer);
 -                 openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer);
 - 
 -                 Array<Vertex> vertices;
 -                 createVertexListFromMesh (aShape.mesh, vertices, Colours::green);
 - 
 -                 openGLContext.extensions.glBufferData (GL_ARRAY_BUFFER,
 -                                                        static_cast<GLsizeiptr> (static_cast<size_t> (vertices.size()) * sizeof (Vertex)),
 -                                                        vertices.getRawDataPointer(), GL_STATIC_DRAW);
 - 
 -                 openGLContext.extensions.glGenBuffers (1, &indexBuffer);
 -                 openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
 -                 openGLContext.extensions.glBufferData (GL_ELEMENT_ARRAY_BUFFER,
 -                                                        static_cast<GLsizeiptr> (static_cast<size_t> (numIndices) * sizeof (juce::uint32)),
 -                                                        aShape.mesh.indices.getRawDataPointer(), GL_STATIC_DRAW);
 -             }
 - 
 -             ~VertexBuffer()
 -             {
 -                 openGLContext.extensions.glDeleteBuffers (1, &vertexBuffer);
 -                 openGLContext.extensions.glDeleteBuffers (1, &indexBuffer);
 -             }
 - 
 -             void bind()
 -             {
 -                 openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer);
 -                 openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
 -             }
 - 
 -             GLuint vertexBuffer, indexBuffer;
 -             int numIndices;
 -             OpenGLContext& openGLContext;
 - 
 -             JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VertexBuffer)
 -         };
 - 
 -         WavefrontObjFile shapeFile;
 -         OwnedArray<VertexBuffer> vertexBuffers;
 - 
 -         static void createVertexListFromMesh (const WavefrontObjFile::Mesh& mesh, Array<Vertex>& list, Colour colour)
 -         {
 -             auto scale = 0.2f;
 -             WavefrontObjFile::TextureCoord defaultTexCoord { 0.5f, 0.5f };
 -             WavefrontObjFile::Vertex defaultNormal { 0.5f, 0.5f, 0.5f };
 - 
 -             for (auto i = 0; i < mesh.vertices.size(); ++i)
 -             {
 -                 const auto& v = mesh.vertices.getReference (i);
 -                 const auto& n = i < mesh.normals.size() ? mesh.normals.getReference (i) : defaultNormal;
 -                 const auto& tc = i < mesh.textureCoords.size() ? mesh.textureCoords.getReference (i) : defaultTexCoord;
 - 
 -                 list.add ({ { scale * v.x, scale * v.y, scale * v.z, },
 -                             { scale * n.x, scale * n.y, scale * n.z, },
 -                             { colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue(), colour.getFloatAlpha() },
 -                             { tc.x, tc.y } });
 -             }
 -         }
 -     };
 - 
 -     const char* vertexShader;
 -     const char* fragmentShader;
 - 
 -     std::unique_ptr<OpenGLShaderProgram> shader;
 -     std::unique_ptr<Shape> shape;
 -     std::unique_ptr<Attributes> attributes;
 -     std::unique_ptr<Uniforms> uniforms;
 - 
 -     String newVertexShader, newFragmentShader;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLAppDemo)
 - };
 
 
  |