├── lib
└── libglsl.so
├── glslutil
├── ShaderIF.o
├── libglsl.so
├── Makefile
├── MakefileMac
├── ShaderIF.h
└── ShaderIF.c++
├── smiley_version1.png
├── smiley_version2.png
├── project1
├── shaders
│ ├── project1.fsh
│ └── project1.vsh
├── Project1_SampleData.txt
├── Makefile
├── ModelView.h
├── main.c++
└── ModelView.c++
├── README.md
└── mvcutil
├── GLFWController.h
├── Controller.h
├── GLFWController.c++
└── Controller.c++
/lib/libglsl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CompSciLauren/opengl-two-smiley-faces/master/lib/libglsl.so
--------------------------------------------------------------------------------
/glslutil/ShaderIF.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CompSciLauren/opengl-two-smiley-faces/master/glslutil/ShaderIF.o
--------------------------------------------------------------------------------
/glslutil/libglsl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CompSciLauren/opengl-two-smiley-faces/master/glslutil/libglsl.so
--------------------------------------------------------------------------------
/smiley_version1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CompSciLauren/opengl-two-smiley-faces/master/smiley_version1.png
--------------------------------------------------------------------------------
/smiley_version2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CompSciLauren/opengl-two-smiley-faces/master/smiley_version2.png
--------------------------------------------------------------------------------
/project1/shaders/project1.fsh:
--------------------------------------------------------------------------------
1 | #version 410 core
2 |
3 | // Complete the placeholder implementation here...
4 | uniform vec3 color;
5 | out vec4 fragmentColor;
6 |
7 | void main()
8 | {
9 | fragmentColor = vec4(color, 1.0);
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/project1/Project1_SampleData.txt:
--------------------------------------------------------------------------------
1 | 6 50
2 | 0 0 20 0 20 40 -20 40 -20 0 0 0
3 | 3 10 5 15 6.5 17.5 8 15
4 | 3 10 5 15 6.5 16.5 8 15
5 | 3 10 -5 15 -6.5 17.5 -8 15
6 | 3 10 -5 15 -6.5 16.5 -8 15
7 | 3 10 -2 11 0 9 2 11
8 | 4 60
9 | -6 6 -3 2 3 2 6 6
10 | 4 60
11 | -6 6 -3 0.5 3 0.5 6 6
--------------------------------------------------------------------------------
/glslutil/Makefile:
--------------------------------------------------------------------------------
1 | CPP = g++ -std=c++11
2 | C_FLAGS = -fPIC -O -c -DGL_GLEXT_PROTOTYPES
3 |
4 | LINK = g++ -fPIC
5 |
6 | OBJS = ShaderIF.o
7 |
8 | libglsl.so: $(OBJS)
9 | $(LINK) -shared -o libglsl.so $(OBJS)
10 | cp libglsl.so ../lib/
11 |
12 | ShaderIF.o: ShaderIF.h ShaderIF.c++
13 | $(CPP) $(C_FLAGS) ShaderIF.c++
14 |
--------------------------------------------------------------------------------
/glslutil/MakefileMac:
--------------------------------------------------------------------------------
1 | CPP = g++ -std=c++11
2 | C_FLAGS = -I/usr/local/include -fPIC -g -c -DGLFW_INCLUDE_GLEXT -DGLFW_INCLUDE_GLCOREARB -DGL_SILENCE_DEPRECATION
3 |
4 | LINK = g++ -fPIC
5 |
6 | OBJS = ShaderIF.o
7 |
8 | libglsl.so: $(OBJS)
9 | $(LINK) -shared -o libglsl.so $(OBJS) -framework OpenGL
10 | cp libglsl.so ../lib/
11 |
12 | ShaderIF.o: ShaderIF.h ShaderIF.c++
13 | $(CPP) $(C_FLAGS) ShaderIF.c++
14 |
--------------------------------------------------------------------------------
/project1/shaders/project1.vsh:
--------------------------------------------------------------------------------
1 | #version 410 core
2 |
3 | // Complete the placeholder implementation here
4 | in vec2 mcPosition; // vertex position
5 | uniform vec4 scaleTrans; // for mapping coordinates into Logical Device Space
6 |
7 | void main()
8 | {
9 | // ldsX = sx * mcX + tx
10 | float ldsX = scaleTrans[0]*mcPosition.x + scaleTrans[1];
11 |
12 | // ldsY = sy * mcY + ty
13 | float ldsY = scaleTrans[2]*mcPosition.y + scaleTrans[3];
14 |
15 | gl_Position = vec4(ldsX, ldsY, 0, 1);
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenGL Two Smiley Faces
2 |
3 | This is my first OpenGL project. When the program runs, you will be able to switch between two different views to see two different versions of a smiley face.
4 |
5 | ## How to Run Program in Terminal
6 |
7 | 1. Clone or download the repo
8 | 2. Inside project1 folder, run `make` command
9 | 3. Type `./main Project1_SampleData.txt`
10 | 4. Press `n` to view n points and `m` to view m points
11 |
12 | ## What it Looks Like
13 |
14 | Here are the two smiley faces you can view. Press `n` to view the first one and `m` to view the second one.
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/project1/Makefile:
--------------------------------------------------------------------------------
1 | CPP = g++ -std=c++11
2 | INC = -I../glslutil -I../mvcutil -I/usr/local/include -I.
3 |
4 | # >>> FOR LINUX, uncomment next few lines; comment out the MAC ones.
5 | C_FLAGS = -fPIC -g -c $(INC) -DGL_GLEXT_PROTOTYPES
6 | GL_LIB_LOC = -L/usr/lib/nvidia-375
7 | GL_LIBRARIES = $(GL_LIB_LOC) -lglfw -lGLU -lGL
8 | MAKE = make
9 | # >>> FOR MAC, uncomment next few lines; comment out previous linux ones.
10 | # C_FLAGS = -fPIC -g -c $(INC) -DGLFW_INCLUDE_GLEXT -DGLFW_INCLUDE_GLCOREARB -DGL_SILENCE_DEPRECATION
11 | # GL_LIBRARIES = -L/usr/local/lib -lglfw -framework OpenGL
12 | # MAKE = make -f MakefileMac
13 | # >>> END: FOR LINUX - FOR MAC
14 |
15 | LINK = g++ -fPIC -g
16 | LOCAL_UTIL_LIBRARIES = ../lib/libglsl.so
17 |
18 | OBJS = main.o ModelView.o Controller.o GLFWController.o
19 |
20 | main: $(OBJS) $(LOCAL_UTIL_LIBRARIES)
21 | $(LINK) -o main $(OBJS) $(LOCAL_UTIL_LIBRARIES) $(GL_LIBRARIES)
22 |
23 | ../lib/libglsl.so: ../glslutil/ShaderIF.h ../glslutil/ShaderIF.c++
24 | (cd ../glslutil; $(MAKE))
25 |
26 | main.o: main.c++
27 | $(CPP) $(C_FLAGS) main.c++
28 | ModelView.o: ModelView.h ModelView.c++
29 | $(CPP) $(C_FLAGS) ModelView.c++
30 | Controller.o: ../mvcutil/Controller.h ../mvcutil/Controller.c++
31 | $(CPP) $(C_FLAGS) -DGLFW_INCLUDE_GLU ../mvcutil/Controller.c++
32 | GLFWController.o: ../mvcutil/GLFWController.h ../mvcutil/GLFWController.c++
33 | $(CPP) $(C_FLAGS) ../mvcutil/GLFWController.c++
34 |
--------------------------------------------------------------------------------
/mvcutil/GLFWController.h:
--------------------------------------------------------------------------------
1 | // GLFWController.h - A concrete Controller subclass using the GLFW window interface
2 |
3 | #ifndef GLFWCONTROLLER_H
4 | #define GLFWCONTROLLER_H
5 |
6 | #include "GLFW/glfw3.h"
7 |
8 | #include "Controller.h"
9 |
10 | class GLFWController : public Controller
11 | {
12 | public:
13 | GLFWController(const std::string& windowTitle, int rcFlags = 0);
14 | virtual ~GLFWController();
15 |
16 | void run();
17 | void setRunWaitsForAnEvent(bool b) { runWaitsForAnEvent = b;}
18 | void setWindowTitle(const std::string& title);
19 |
20 | protected:
21 | GLFWController(const GLFWController& c) : Controller(c) {}
22 |
23 | virtual void handleDisplay();
24 | void initializeCallbacksForRC();
25 | void prepareWindow() const;
26 | void reportWindowInterfaceVersion(std::ostream& os) const;
27 | void swapBuffers() const { glfwSwapBuffers(theWindow); }
28 |
29 | GLFWwindow* theWindow;
30 | private:
31 | bool returnFromRun, runWaitsForAnEvent;
32 | int lastPixelPosX, lastPixelPosY;
33 |
34 | void createWindowAndRC(const std::string& windowTitle, int rcFlags);
35 |
36 | static int numGLFWControllers;
37 |
38 | static void charCB(GLFWwindow* window, unsigned int theChar);
39 | static void keyboardCB(GLFWwindow* window, int key, int scanCode, int action, int mods);
40 | static void mouseMotionCB(GLFWwindow* window, double x, double y);
41 | static void reshapeCB(GLFWwindow* window, int width, int height);
42 | };
43 |
44 | #endif
45 |
--------------------------------------------------------------------------------
/mvcutil/Controller.h:
--------------------------------------------------------------------------------
1 | // Controller.h - An Abstract base Class for a Controller (in Model-View-Controller sense)
2 |
3 | #ifndef CONTROLLER_H
4 | #define CONTROLLER_H
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | class ModelView;
12 |
13 | class Controller
14 | {
15 | public:
16 | Controller();
17 | virtual ~Controller();
18 |
19 | void addModel(ModelView* m);
20 | void getOverallMCBoundingBox(double* xyzLimits) const;
21 | double getViewportAspectRatio() const; // height/width
22 | virtual void redraw() {} // to force a display update
23 | void reportVersions(std::ostream& os) const;
24 | virtual void run() = 0;
25 | virtual void setWindowTitle(const std::string& title) = 0;
26 |
27 | static bool checkForErrors(std::ostream& os, const std::string& context);
28 | static Controller* getCurrentController() { return curController; }
29 | static void setNewWindowSize(int width, int height);
30 |
31 | protected:
32 | Controller(const Controller& c) {}
33 | std::vector models;
34 |
35 | // Virtual methods for event handling (any can be overridden)
36 | // --> Keyboard-related event handling
37 | virtual void handleAsciiChar(unsigned char theChar, int x, int y);
38 |
39 | // --> Window-related event handling
40 | virtual void handleReshape(int width, int height);
41 |
42 | // --> Miscellaneous
43 | virtual void endProgram() { exit(0); }
44 | void pixelPointToLDSPoint(int x, int y, double& ldsX, double& ldsY);
45 | void pixelVectorToLDSVector(int dx, int dy, double& ldsDX, double& ldsDY);
46 | virtual void renderAllModels();
47 | virtual void reportWindowInterfaceVersion(std::ostream& os) const = 0;
48 | virtual void swapBuffers() const = 0;
49 |
50 | // Data the Controller uses to track the overall MC box bounding all models.
51 | double overallMCBoundingBox[6];
52 | int glClearFlags;
53 |
54 | static Controller* curController;
55 | static int newWindowWidth, newWindowHeight;
56 | static std::string titleString(const std::string& str);
57 |
58 | private:
59 | void updateMCBoundingBox(ModelView* m);
60 | };
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/glslutil/ShaderIF.h:
--------------------------------------------------------------------------------
1 | // ShaderIF.h: Basic interface to read, compile, and link GLSL Shader programs
2 |
3 | #ifndef SHADERIF_H
4 | #define SHADERIF_H
5 |
6 | #ifdef __APPLE_CC__
7 | #include "GLFW/glfw3.h"
8 | #else
9 | #include
10 | #endif
11 |
12 | #include
13 |
14 | class ShaderIF
15 | {
16 | public:
17 | struct ShaderSpec
18 | {
19 | std::string fName;
20 | GLenum sType;
21 | };
22 | // Creating and managing shader programs:
23 | // Create an instance with one of the following two constructors
24 | // and use the getShaderPgmID() method to get the shader program ID.
25 | // For example:
26 | // ShaderIF* sIF = new ShaderIF("MyShader.vsh", "MyShader.fsh");
27 | // int pgmId = sIF->getShaderPgmID();
28 | // Implementation note for android deviecs: note that the Rendering
29 | // Context (including, but not limited to GLSL shader programs) is
30 | // sometimes destroyed while your program is running, most notably
31 | // whenever the device is rotated, the "home" key pressed, etc. When
32 | // this happens, you must be prepared to recognize that the shader
33 | // program must be recreated.
34 | ShaderIF(const std::string& vShader, const std::string& fShader);
35 | ShaderIF(const ShaderSpec* shaders, int nShaders);
36 | virtual ~ShaderIF();
37 | int getShaderPgmID() const { return shaderPgm; }
38 |
39 | // Lookup routines for per-vertex and per-primitive (uniform) variables:
40 | GLint ppuExists(const std::string& name); // per-primitive (uniform)
41 | GLint ppuLoc(const std::string& name); // per-primitive (uniform)
42 | GLint pvaExists(const std::string& name); // per-vertex attribute
43 | GLint pvaLoc(const std::string& name); // per-vertex attribute
44 | private:
45 | struct Shader
46 | {
47 | std::string fName;
48 | GLenum sType;
49 | std::string source;
50 | int pgmID;
51 |
52 | Shader(): fName(""), sType(0), source(""), pgmID(0) {}
53 | };
54 | void destroy();
55 | void initShaders();
56 |
57 | static bool readShaderSource(Shader& shader);
58 |
59 | int shaderPgm;
60 | int numShaderComponents;
61 | Shader* shaders;
62 | };
63 |
64 | #endif
65 |
--------------------------------------------------------------------------------
/project1/ModelView.h:
--------------------------------------------------------------------------------
1 | // ModelView.h - a basic combined Model and View for OpenGL
2 |
3 | #ifndef MODELVIEW_H
4 | #define MODELVIEW_H
5 |
6 | #include "ShaderIF.h"
7 |
8 | #include
9 |
10 | #ifdef __APPLE_CC__
11 | #include "GLFW/glfw3.h"
12 | #else
13 | #include
14 | #endif
15 |
16 | // for interfacing to common GLSL data types
17 | typedef float vec2[2];
18 | typedef float vec3[3];
19 |
20 | class ModelView
21 | {
22 | public:
23 | ModelView(ShaderIF* sIF, vec2* nVertexPositions, int nPoints, int mPoints, vec2* mVertexPositions);
24 | virtual ~ModelView();
25 |
26 | // xyzLimits: {mcXmin, mcXmax, mcYmin, mcYmax, mcZmin, mcZmax}
27 | void getMCBoundingBox(double* xyzLimits) const;
28 | bool handleCommand(unsigned char anASCIIChar, double ldsX, double ldsY);
29 | void render() const;
30 |
31 | // viewing controls common to 2D and 3D
32 | static void setAspectRatioPreservationEnabled(bool b)
33 | { aspectRatioPreservationEnabled = b; }
34 | static void setMCRegionOfInterest(double xyz[6]);
35 |
36 | private:
37 | GLuint vao[2];
38 | GLuint vbo[2];
39 | int nTotalPoints;
40 | int mTotalPoints;
41 | float xmin, xmax, ymin, ymax;
42 | vec3 nColor;
43 | vec3 mColor;
44 |
45 | ShaderIF* shaderIF;
46 |
47 | void deleteObject();
48 |
49 | void initModelGeometry(vec2* nVertexPositions, vec2* mVertexPositions);
50 |
51 | // Routines for computing parameters necessary to map from arbitrary
52 | // model coordinate ranges into OpenGL's -1..+1 Logical Device Space.
53 | // 1. linearMap determines the scale and translate parameters needed in
54 | // order to map a value, f (fromMin <= f <= fromMax) to its corresponding
55 | // value, t (toMin <= t <= toMax). Specifically: t = scale*f + trans.
56 | static void linearMap(double fromMin, double fromMax,
57 | double toMin, double toMax, double& scale, double& trans);
58 | // 2. matchAspectRatio modifies (xmin,xmax) OR (ymin,ymax) to center that
59 | // region in an expanded window that matches the given aspect ratio.
60 | static void matchAspectRatio(double& xmin, double& xmax,
61 | double& ymin, double& ymax, double vAR);
62 | // 3. compute2DScaleTrans uses the current model coordinate region of
63 | // interest - modified as necessary to preserve aspect ratios - and
64 | // then passes the modified limits to linearMap to compute the scale
65 | // and translation needed to map MC to LDS.
66 | // (The scales and translationes are returned in float[] because
67 | // glUniform currently allows only float[].)
68 | static void compute2DScaleTrans(float* scaleTrans);
69 |
70 | static double mcRegionOfInterest[6];
71 | static bool aspectRatioPreservationEnabled;
72 | };
73 |
74 | #endif
75 |
--------------------------------------------------------------------------------
/project1/main.c++:
--------------------------------------------------------------------------------
1 | // main.c++
2 |
3 | #include "GLFWController.h"
4 | #include "ModelView.h"
5 | #include
6 | #include
7 |
8 | void createScene(GLFWController& c, ShaderIF* sIF, float xValues[], float yValues[], int totalNPoints, int totalMPoints)
9 | {
10 | float dt = 1.0 / (totalMPoints - 1);
11 | vec2 nVertexPositions[totalNPoints];
12 | vec2 buf[totalNPoints];
13 | vec2* mVertexPositions = new vec2[totalMPoints];
14 | float t;
15 |
16 | for (int i = 0; i < totalNPoints; i++)
17 | {
18 | nVertexPositions[i][0] = xValues[i];
19 | nVertexPositions[i][1] = yValues[i];
20 | }
21 |
22 | for (int i = 0; i < totalMPoints; i++)
23 | {
24 | for (int a = 0; a < totalNPoints; a++)
25 | {
26 | buf[a][0] = nVertexPositions[a][0];
27 | buf[a][1] = nVertexPositions[a][1];
28 | }
29 |
30 | t = i * dt;
31 | for (int j = 0; j <= totalNPoints - 2; j++)
32 | {
33 | for (int k = 0; k <= totalNPoints - j - 2; k++)
34 | {
35 | buf[k][0] = (1 - t) * buf[k][0] + t * buf[k + 1][0];
36 | buf[k][1] = (1 - t) * buf[k][1] + t * buf[k + 1][1];
37 | }
38 | }
39 | // i-th point for the VBO is now in buf[0]
40 | mVertexPositions[i][0] = buf[0][0];
41 | mVertexPositions[i][1] = buf[0][1];
42 | }
43 |
44 | c.addModel(new ModelView(sIF, nVertexPositions, totalNPoints, totalMPoints, mVertexPositions));
45 | }
46 |
47 | int main(int argc, char* argv[])
48 | {
49 | GLFWController c(argv[0]);
50 | c.reportVersions(std::cout);
51 |
52 | ShaderIF* sIF = new ShaderIF("shaders/project1.vsh", "shaders/project1.fsh");
53 |
54 | int totalNPoints = 0;
55 | int totalMPoints = 0;
56 |
57 | std::ifstream userFileChoice;
58 | std::string fileName = argv[1];
59 | userFileChoice.open(fileName);
60 | if(!userFileChoice.is_open())
61 | {
62 | std::cout << "Failed to open file. File was not found.\n";
63 | exit(1);
64 | }
65 | while (!userFileChoice.eof())
66 | {
67 | userFileChoice >> totalNPoints;
68 | userFileChoice >> totalMPoints;
69 | float xValues[totalNPoints];
70 | float yValues[totalNPoints];
71 |
72 | for (int i = 0; i < totalNPoints; i++)
73 | {
74 | userFileChoice >> xValues[i];
75 | userFileChoice >> yValues[i];
76 | }
77 |
78 | createScene(c, sIF, xValues, yValues, totalNPoints, totalMPoints);
79 | }
80 |
81 | // initialize 2D viewing information:
82 | // Get the overall scene bounding box in Model Coordinates:
83 | double xyz[6]; // xyz limits, even though this is 2D
84 | c.getOverallMCBoundingBox(xyz);
85 | std::cout << "Bounding box: " << xyz[0] << " <= x <= " << xyz[1] << '\n';
86 | std::cout << " " << xyz[2] << " <= y <= " << xyz[3] << '\n';
87 | std::cout << " " << xyz[4] << " <= z <= " << xyz[5] << "\n\n";
88 | // Tell class ModelView we initially want to see the whole scene:
89 | ModelView::setMCRegionOfInterest(xyz);
90 |
91 | glClearColor(1.0, 1.0, 1.0, 1.0);
92 | c.run();
93 |
94 | delete sIF;
95 | userFileChoice.close();
96 | return 0;
97 | }
98 |
--------------------------------------------------------------------------------
/mvcutil/GLFWController.c++:
--------------------------------------------------------------------------------
1 | // GLFWController.c++: a basic GLFWController (in Model-View-GLFWController sense)
2 |
3 | #include
4 |
5 | #include "GLFWController.h"
6 | #include "ModelView.h"
7 |
8 | int GLFWController::numGLFWControllers = 0;
9 |
10 | GLFWController::GLFWController(const std::string& windowTitle, int rcFlags) :
11 | theWindow(nullptr),
12 | returnFromRun(false), runWaitsForAnEvent(true),
13 | lastPixelPosX(0), lastPixelPosY(0)
14 | {
15 | if (numGLFWControllers++ == 0)
16 | glfwInit();
17 |
18 | // First create the window and its Rendering Context (RC)
19 | createWindowAndRC(windowTitle, rcFlags);
20 | }
21 |
22 | GLFWController::~GLFWController()
23 | {
24 | if (theWindow != nullptr)
25 | glfwDestroyWindow(theWindow);
26 |
27 | if (--numGLFWControllers == 0)
28 | glfwTerminate();
29 | }
30 |
31 | void GLFWController::charCB(GLFWwindow* window, unsigned int theChar)
32 | {
33 | if (theChar < 128)
34 | {
35 | GLFWController* c = dynamic_cast(curController);
36 | c->handleAsciiChar(
37 | static_cast(theChar), c->lastPixelPosX, c->lastPixelPosY);
38 | }
39 | }
40 |
41 | void GLFWController::createWindowAndRC(const std::string& windowTitle, int rcFlags)
42 | {
43 | // The following calls enforce use of only non-deprecated functionality.
44 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
45 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
46 |
47 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
48 | int minor = 8; // Start AT LEAST one greater than where you really want to start
49 | while ((theWindow == nullptr) && (minor > 0))
50 | {
51 | minor--;
52 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor);
53 | theWindow = glfwCreateWindow(newWindowWidth, newWindowHeight, titleString(windowTitle).c_str(), nullptr, nullptr);
54 | }
55 | if (theWindow == nullptr)
56 | {
57 | std::cerr << "\n**** COULD NOT CREATE A 4.x RENDERING CONTEXT ****\n\n";
58 | return;
59 | }
60 |
61 | glfwMakeContextCurrent(theWindow);
62 | initializeCallbacksForRC();
63 | }
64 |
65 | void GLFWController::handleDisplay()
66 | {
67 | prepareWindow();
68 | // clear the frame buffer
69 | glClear(glClearFlags);
70 |
71 | renderAllModels();
72 |
73 | glfwSwapBuffers(theWindow);
74 |
75 | checkForErrors(std::cout, "GLFWController::handleDisplay");
76 | }
77 |
78 | void GLFWController::initializeCallbacksForRC()
79 | {
80 | glfwSetWindowSizeCallback(theWindow, reshapeCB);
81 | glfwSetCharCallback(theWindow, charCB);
82 | glfwSetKeyCallback(theWindow, keyboardCB);
83 | glfwSetCursorPosCallback(theWindow, mouseMotionCB);
84 | }
85 |
86 | void GLFWController::keyboardCB(GLFWwindow* window, int key, int scanCode, int action, int mods)
87 | {
88 | if (curController != nullptr)
89 | {
90 | GLFWController* theC = dynamic_cast(curController);
91 | if ((key == GLFW_KEY_ESCAPE) && (action != GLFW_PRESS))
92 | theC->handleAsciiChar(27, theC->lastPixelPosX, theC->lastPixelPosY);
93 | }
94 | }
95 |
96 | void GLFWController::mouseMotionCB(GLFWwindow* window, double x, double y)
97 | {
98 | if (curController != nullptr)
99 | {
100 | GLFWController* c = dynamic_cast(curController);
101 | c->lastPixelPosX = static_cast(x + 0.5);
102 | c->lastPixelPosY = static_cast(y + 0.5);
103 | }
104 | }
105 |
106 | void GLFWController::prepareWindow() const
107 | {
108 | #ifdef __APPLE__
109 | if (theWindow == nullptr)
110 | return;
111 | glfwMakeContextCurrent(theWindow);
112 | int width, height;
113 | glfwGetFramebufferSize(theWindow, &width, &height);
114 | glViewport(0, 0, width, height);
115 | #endif
116 | }
117 |
118 | void GLFWController::reportWindowInterfaceVersion(std::ostream& os) const
119 | {
120 | os << " GLFW: " << glfwGetVersionString() << '\n';
121 | }
122 |
123 | void GLFWController::reshapeCB(GLFWwindow* window, int width, int height)
124 | {
125 | dynamic_cast(curController)->handleReshape(width, height);
126 | }
127 |
128 | void GLFWController::run()
129 | {
130 | if (theWindow == nullptr)
131 | return;
132 | while (!glfwWindowShouldClose(theWindow) && !returnFromRun)
133 | {
134 | if (runWaitsForAnEvent)
135 | glfwWaitEvents();
136 | else
137 | glfwPollEvents();
138 | handleDisplay();
139 | }
140 | glfwDestroyWindow(theWindow);
141 | theWindow = nullptr;
142 | }
143 |
144 | void GLFWController::setWindowTitle(const std::string& title)
145 | {
146 | if (theWindow != nullptr)
147 | glfwSetWindowTitle(theWindow, title.c_str());
148 | }
149 |
--------------------------------------------------------------------------------
/glslutil/ShaderIF.c++:
--------------------------------------------------------------------------------
1 | // ShaderIF.c++: Basic interface to read, compile, and link GLSL Shader programs
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "ShaderIF.h"
9 |
10 | ShaderIF::ShaderIF(const std::string& vShader, const std::string& fShader) :
11 | shaderPgm(0), numShaderComponents(2) // just a vertex & fragment shader
12 | {
13 | shaders = new Shader[numShaderComponents];
14 | shaders[0].fName = vShader;
15 | shaders[0].sType = GL_VERTEX_SHADER;
16 | shaders[1].fName = fShader;
17 | shaders[1].sType = GL_FRAGMENT_SHADER;
18 | initShaders();
19 | }
20 |
21 | ShaderIF::ShaderIF(const ShaderSpec* shaders, int nShaders) :
22 | shaderPgm(0), numShaderComponents(nShaders)
23 | {
24 | this->shaders = new Shader[numShaderComponents];
25 | for (int i=0 ; ishaders[i].fName = shaders[i].fName;
28 | this->shaders[i].sType = shaders[i].sType;
29 | }
30 | initShaders();
31 | }
32 |
33 | ShaderIF::~ShaderIF()
34 | {
35 | if (shaders != nullptr)
36 | {
37 | destroy();
38 | delete [] shaders;
39 | shaders = nullptr;
40 | }
41 | }
42 |
43 | void ShaderIF::destroy()
44 | {
45 | for (int si=0 ; si 0)
49 | {
50 | if (glIsShader(sPgmID))
51 | glDeleteShader(sPgmID);
52 | shaders[si].pgmID = 0;
53 | }
54 | }
55 | if (shaderPgm > 0)
56 | {
57 | if (glIsProgram(shaderPgm))
58 | glDeleteProgram(shaderPgm);
59 | }
60 | shaderPgm = 0;
61 | numShaderComponents = 0;
62 | }
63 |
64 | void ShaderIF::initShaders()
65 | {
66 | for (int i = 0; i < numShaderComponents; i++ )
67 | {
68 | if (!readShaderSource(shaders[i]))
69 | return;
70 |
71 | shaders[i].pgmID = glCreateShader(shaders[i].sType);
72 | const char* src = shaders[i].source.c_str();
73 | glShaderSource(shaders[i].pgmID, 1, &src, nullptr);
74 | glCompileShader(shaders[i].pgmID);
75 |
76 | GLint compiled;
77 | glGetShaderiv(shaders[i].pgmID, GL_COMPILE_STATUS, &compiled );
78 | if ( !compiled )
79 | {
80 | std::cerr << shaders[i].fName << " failed to compile:" << std::endl;
81 | GLint logSize;
82 | glGetShaderiv(shaders[i].pgmID, GL_INFO_LOG_LENGTH, &logSize );
83 | if (logSize <= 0)
84 | std::cerr << "No log information available (" << logSize << ")\n";
85 | else
86 | {
87 | try
88 | {
89 | char* logMsg = new char[logSize];
90 | glGetShaderInfoLog(shaders[i].pgmID, logSize, nullptr, logMsg );
91 | std::cerr << "ERROR LOG: '" << logMsg << "'\n";
92 | delete [] logMsg;
93 | }
94 | catch (std::bad_alloc bae)
95 | {
96 | std::cerr << "Could not allocate error log buffer of size: " << logSize << std::endl;
97 | }
98 | }
99 | destroy();
100 | return;
101 | }
102 | }
103 |
104 | shaderPgm = glCreateProgram();
105 | for (int i=0 ; i
7 | #include
8 | #endif
9 |
10 | #include "Controller.h"
11 | #include "ModelView.h"
12 |
13 | Controller* Controller::curController = nullptr;
14 | int Controller::newWindowWidth = 512;
15 | int Controller::newWindowHeight = 512;
16 |
17 | Controller::Controller() : glClearFlags(GL_COLOR_BUFFER_BIT)
18 | {
19 | Controller::curController = this;
20 |
21 | // indicate we do not yet have any models by setting min to +1 and max to -1:
22 | overallMCBoundingBox[0] = overallMCBoundingBox[2] = overallMCBoundingBox[4] = 1.0;
23 | overallMCBoundingBox[1] = overallMCBoundingBox[3] = overallMCBoundingBox[5] = -1.0;
24 | }
25 |
26 | Controller::~Controller()
27 | {
28 | if (this == curController)
29 | curController = nullptr;
30 | }
31 |
32 | void Controller::addModel(ModelView* m)
33 | {
34 | if (m == nullptr)
35 | return;
36 | models.push_back(m);
37 | updateMCBoundingBox(m);
38 | }
39 |
40 | bool Controller::checkForErrors(std::ostream& os, const std::string& context)
41 | // CLASS METHOD
42 | {
43 | bool hadError = false;
44 | GLenum e = glGetError();
45 | while (e != GL_NO_ERROR)
46 | {
47 | os << "CheckForErrors (context: " << context
48 | #ifdef __APPLE__
49 | << "): " << static_cast(e) << std::endl;
50 | #else
51 | << "): " << static_cast(gluErrorString(e)) << std::endl;
52 | #endif
53 | e = glGetError();
54 | hadError = true;
55 | }
56 | return hadError;
57 | }
58 |
59 | void Controller::getOverallMCBoundingBox(double xyzLimits[]) const
60 | {
61 | for (int i=0 ; i<6 ; i++)
62 | xyzLimits[i] = overallMCBoundingBox[i];
63 | }
64 |
65 | double Controller::getViewportAspectRatio() const
66 | {
67 | int vp[4];
68 | glGetIntegerv(GL_VIEWPORT, vp);
69 | return static_cast(vp[3]) / static_cast(vp[2]);
70 | }
71 |
72 | void Controller::handleAsciiChar(unsigned char theChar, int x, int y)
73 | {
74 | const unsigned char ESC = 27;
75 | if (theChar == ESC)
76 | endProgram();
77 | else
78 | {
79 | // No other character is currently handled by the Controller, so we
80 | // just send the event information to the model.
81 |
82 | double ldsX, ldsY; // only coord system known to both Controller and ModelView
83 | pixelPointToLDSPoint(x, y, ldsX, ldsY);
84 |
85 | // Pass the event to each registered ModelView, stopping if and when
86 | // an instance tells us not to pass it to any others.
87 | for (std::vector::iterator it=models.begin() ; ithandleCommand(theChar, ldsX, ldsY))
89 | break;
90 |
91 | redraw();
92 | }
93 | }
94 |
95 | void Controller::handleReshape(int width, int height)
96 | {
97 | glViewport(0, 0, width, height);
98 | redraw();
99 | }
100 |
101 | void Controller::pixelPointToLDSPoint(int xIn, int yIn, double& ldsX, double& ldsY)
102 | {
103 | int vp[4];
104 | glGetIntegerv(GL_VIEWPORT, vp);
105 | double x = xIn - vp[0];
106 | ldsX = 2.0 * x / static_cast(vp[2]) - 1.0;
107 | // The window managers report pixel coordinates assuming y=0 is at the top
108 | // of the window. The main OpenGL API assumes y=0 is at the bottom, hence:
109 | double y = (vp[3] - yIn) - vp[1];
110 | ldsY = 2.0 * y / static_cast(vp[3]) - 1.0;
111 | }
112 |
113 | void Controller::pixelVectorToLDSVector(int dxIn, int dyIn, double& ldsDX, double& ldsDY)
114 | {
115 | int vp[4];
116 | glGetIntegerv(GL_VIEWPORT, vp);
117 | ldsDX = 2.0 * static_cast(dxIn) / static_cast(vp[2]);
118 | // The window managers delta y is positive going down the screen; In LDS space,
119 | // delta y is positive going up the screen. Hence the leading "-":
120 | ldsDY = -2.0 * static_cast(dyIn) / static_cast(vp[3]);
121 | }
122 |
123 | void Controller::renderAllModels()
124 | {
125 | // draw the collection of models
126 | for (std::vector::iterator it=models.begin() ; itrender();
128 | }
129 |
130 | void Controller::reportVersions(std::ostream& os) const
131 | {
132 | const char* glVer = reinterpret_cast(glGetString(GL_VERSION));
133 | const char* glslVer = reinterpret_cast
134 | (glGetString(GL_SHADING_LANGUAGE_VERSION));
135 | // glGetString can return nullptr if no rendering context has been created
136 | os << "VERSIONS: GL: ";
137 | if (glVer == nullptr)
138 | os << "nullptr (has RC been created?)\n";
139 | else
140 | os << glVer << '\n';
141 | os << " GLSL: ";
142 | if (glslVer == nullptr)
143 | os << "nullptr (has RC been created?)\n";
144 | else
145 | os << glslVer << '\n';
146 | reportWindowInterfaceVersion(os);
147 | }
148 |
149 | void Controller::setNewWindowSize(int width, int height)
150 | {
151 | newWindowWidth = width; newWindowHeight = height;
152 | }
153 |
154 | std::string Controller::titleString(const std::string& str)
155 | {
156 | int lastSlash = str.length() - 1;
157 | while (lastSlash > 0)
158 | {
159 | if (str[lastSlash] == '/')
160 | return str.substr(lastSlash+1);
161 | lastSlash--;
162 | }
163 | // No slashes - just return original string
164 | return str;
165 | }
166 |
167 | void Controller::updateMCBoundingBox(ModelView* m)
168 | {
169 | if (m == nullptr)
170 | return;
171 | if (overallMCBoundingBox[0] <= overallMCBoundingBox[1])
172 | {
173 | // bounding box already initialized; just update it:
174 | double xyz[6];
175 | m->getMCBoundingBox(xyz);
176 | if (xyz[0] > xyz[1])
177 | // This model does not want to be included in BBs
178 | return;
179 | for (int i=0 ; i<5 ; i+=2)
180 | {
181 | if (xyz[i] < overallMCBoundingBox[i])
182 | overallMCBoundingBox[i] = xyz[i];
183 | if (xyz[i+1] > overallMCBoundingBox[i+1])
184 | overallMCBoundingBox[i+1] = xyz[i+1];
185 | }
186 | }
187 | else // use this model to initialize the bounding box
188 | m->getMCBoundingBox(overallMCBoundingBox);
189 | }
190 |
--------------------------------------------------------------------------------
/project1/ModelView.c++:
--------------------------------------------------------------------------------
1 | // ModelView.c++ - a basic combined Model and View for OpenGL
2 |
3 | #include
4 |
5 | #include "ModelView.h"
6 | #include "Controller.h"
7 | #include "ShaderIF.h"
8 |
9 | double ModelView::mcRegionOfInterest[6] = { -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 };
10 | bool ModelView::aspectRatioPreservationEnabled = true;
11 |
12 | ModelView::ModelView(ShaderIF* sIF, vec2* triangleVertices, int nPoints, int mPoints, vec2* mVertexPositions) : shaderIF(sIF)
13 | {
14 | nTotalPoints = nPoints;
15 | mTotalPoints = mPoints;
16 | initModelGeometry(triangleVertices, mVertexPositions);
17 | }
18 |
19 | ModelView::~ModelView()
20 | {
21 | deleteObject();
22 | }
23 |
24 | void ModelView::deleteObject()
25 | {
26 | if (vao[0] > 0) // not already deleted
27 | {
28 | glDeleteBuffers(1, vbo);
29 | glDeleteVertexArrays(1, vao);
30 | vao[0] = vbo[0] = 0;
31 | }
32 | }
33 |
34 | void ModelView::compute2DScaleTrans(float* scaleTransF)
35 | {
36 | double xmin = mcRegionOfInterest[0];
37 | double xmax = mcRegionOfInterest[1];
38 | double ymin = mcRegionOfInterest[2];
39 | double ymax = mcRegionOfInterest[3];
40 |
41 | if (aspectRatioPreservationEnabled)
42 | {
43 | // preserve aspect ratio. Make "region of interest" wider or taller to
44 | // match the Controller's viewport aspect ratio.
45 | double vAR = Controller::getCurrentController()->getViewportAspectRatio();
46 | matchAspectRatio(xmin, xmax, ymin, ymax, vAR);
47 | }
48 |
49 | // We are only concerned with the xy extents for now, hence we will
50 | // ignore mcRegionOfInterest[4] and mcRegionOfInterest[5].
51 | // Map the overall limits to the -1..+1 range expected by the OpenGL engine
52 | double scaleTrans[4];
53 | linearMap(xmin, xmax, -1.0, 1.0, scaleTrans[0], scaleTrans[1]);
54 | linearMap(ymin, ymax, -1.0, 1.0, scaleTrans[2], scaleTrans[3]);
55 | for (int i=0 ; i<4 ; i++)
56 | scaleTransF[i] = static_cast(scaleTrans[i]);
57 | }
58 |
59 | // xyzLimits: {mcXmin, mcXmax, mcYmin, mcYmax, mcZmin, mcZmax}
60 | void ModelView::getMCBoundingBox(double* xyzLimits) const
61 | {
62 | xyzLimits[0] = xmin;
63 | xyzLimits[1] = xmax;
64 | xyzLimits[2] = ymin;
65 | xyzLimits[3] = ymax;
66 | xyzLimits[4] = -1.0; // [4] and [5] are
67 | xyzLimits[5] = 1.0; // (zmin, zmax) but really it's 0..0
68 | }
69 |
70 | bool toggle = true;
71 |
72 | bool ModelView::handleCommand(unsigned char anASCIIChar, double ldsX, double ldsY)
73 | {
74 | if (anASCIIChar == 'n')
75 | {
76 | toggle = true;
77 | }
78 | else if (anASCIIChar == 'm')
79 | {
80 | toggle = false;
81 | }
82 | return true; // not intended for me; tell Controller to keep trying
83 | }
84 |
85 | void ModelView::initModelGeometry(vec2* nVertexPositions, vec2* mVertexPositions)
86 | {
87 | // set color for n
88 | nColor[0] = 1; nColor[1] = 0.5; nColor[2] = 0.2;
89 |
90 | // set color for m
91 | mColor[0] = 0.4; mColor[1] = 0.9; mColor[2] = 0.7;
92 |
93 | // create VAOs and VBOs
94 | glGenVertexArrays(2, vao);
95 | glGenBuffers(2, vbo);
96 |
97 | // initialize these for n
98 | glBindVertexArray(vao[0]);
99 | glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
100 |
101 | // allocate space and send data to GPU for n
102 | int numBytesInBuffer = nTotalPoints * sizeof(vec2);
103 | glBufferData(GL_ARRAY_BUFFER, numBytesInBuffer, nVertexPositions, GL_STATIC_DRAW);
104 | glVertexAttribPointer(shaderIF->pvaLoc("mcPosition"), 2, GL_FLOAT, GL_FALSE, 0, 0);
105 | glEnableVertexAttribArray(shaderIF->pvaLoc("mcPosition"));
106 |
107 | // initialize these for m
108 | glBindVertexArray(vao[1]);
109 | glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
110 |
111 | // allocate space and send data to GPU for m
112 | int numBytesInBufferM = mTotalPoints * sizeof(vec2);
113 | glBufferData(GL_ARRAY_BUFFER, numBytesInBufferM, mVertexPositions, GL_STATIC_DRAW);
114 | glVertexAttribPointer(shaderIF->pvaLoc("mcPosition"), 2, GL_FLOAT, GL_FALSE, 0, 0);
115 | glEnableVertexAttribArray(shaderIF->pvaLoc("mcPosition"));
116 |
117 | // determine and remember min/max coordinates
118 | xmin = xmax = nVertexPositions[0][0];
119 | ymin = ymax = nVertexPositions[0][1];
120 |
121 | for (int i = 0; i < nTotalPoints; i++)
122 | {
123 | if (nVertexPositions[i][0] < xmin)
124 | {
125 | xmin = nVertexPositions[i][0];
126 | }
127 | else if (nVertexPositions[i][0] > xmax)
128 | {
129 | xmax = nVertexPositions[i][0];
130 | }
131 |
132 | if (nVertexPositions[i][1] < ymin)
133 | {
134 | ymin = nVertexPositions[i][1];
135 | }
136 | else if (nVertexPositions[i][1] > ymax)
137 | {
138 | ymax = nVertexPositions[i][1];
139 | }
140 | }
141 |
142 | for (int i = 0; i < mTotalPoints; i++)
143 | {
144 | if (mVertexPositions[i][0] < xmin)
145 | {
146 | xmin = mVertexPositions[i][0];
147 | }
148 | else if (mVertexPositions[i][0] > xmax)
149 | {
150 | xmax = mVertexPositions[i][0];
151 | }
152 |
153 | if (mVertexPositions[i][1] < ymin)
154 | {
155 | ymin = mVertexPositions[i][1];
156 | }
157 | else if (mVertexPositions[i][1] > ymax)
158 | {
159 | ymax = mVertexPositions[i][1];
160 | }
161 | }
162 | }
163 |
164 | // linearMap determines the scale and translate parameters needed in
165 | // order to map a value, f (fromMin <= f <= fromMax) to its corresponding
166 | // value, t (toMin <= t <= toMax). Specifically: t = scale*f + trans.
167 | void ModelView::linearMap(double fromMin, double fromMax, double toMin, double toMax,
168 | double& scale, double& trans) // CLASS METHOD
169 | {
170 | scale = (toMax - toMin) / (fromMax - fromMin);
171 | trans = toMin - scale*fromMin;
172 | }
173 |
174 | void ModelView::matchAspectRatio(double& xmin, double& xmax,
175 | double& ymin, double& ymax, double vAR)
176 | {
177 | double wHeight = ymax - ymin;
178 | double wWidth = xmax - xmin;
179 | double wAR = wHeight / wWidth;
180 | if (wAR > vAR)
181 | {
182 | // make window wider
183 | wWidth = wHeight / vAR;
184 | double xmid = 0.5 * (xmin + xmax);
185 | xmin = xmid - 0.5*wWidth;
186 | xmax = xmid + 0.5*wWidth;
187 | }
188 | else
189 | {
190 | // make window taller
191 | wHeight = wWidth * vAR;
192 | double ymid = 0.5 * (ymin + ymax);
193 | ymin = ymid - 0.5*wHeight;
194 | ymax = ymid + 0.5*wHeight;
195 | }
196 | }
197 |
198 | void ModelView::render() const
199 | {
200 | // save the current GLSL program in use
201 | GLint pgm;
202 | glGetIntegerv(GL_CURRENT_PROGRAM, &pgm);
203 |
204 | // draw the triangles using our vertex and fragment shaders
205 | glUseProgram(shaderIF->getShaderPgmID());
206 |
207 | // set scaleTrans (and all other needed) uniform(s)
208 | float scaleTrans[4];
209 | compute2DScaleTrans(scaleTrans);
210 | glUniform4fv(shaderIF->ppuLoc("scaleTrans"), 1, scaleTrans);
211 |
212 | // make require primitive call(s)
213 | if (toggle == true)
214 | {
215 | glUniform3fv(shaderIF->ppuLoc("color"), 1, nColor); // establish the color for n
216 | glBindVertexArray(vao[0]);
217 | glDrawArrays(GL_LINE_STRIP, 0, nTotalPoints);
218 | }
219 | else
220 | {
221 | glUniform3fv(shaderIF->ppuLoc("color"), 1, mColor); // establish the color for m
222 | glBindVertexArray(vao[1]);
223 | glDrawArrays(GL_LINE_STRIP, 0, mTotalPoints);
224 | }
225 |
226 | // restore the previous program
227 | glUseProgram(pgm);
228 | }
229 |
230 | void ModelView::setMCRegionOfInterest(double xyz[6])
231 | {
232 | for (int i=0 ; i<6 ; i++)
233 | mcRegionOfInterest[i] = xyz[i];
234 | }
235 |
--------------------------------------------------------------------------------