You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
		
		
		
		
		
			
		
			
				
					
					
						
							511 lines
						
					
					
						
							14 KiB
						
					
					
				
			
		
		
	
	
							511 lines
						
					
					
						
							14 KiB
						
					
					
				//======================================================================== | 
						|
// This is an example program for the GLFW library | 
						|
// | 
						|
// The program uses a "split window" view, rendering four views of the | 
						|
// same scene in one window (e.g. uesful for 3D modelling software). This | 
						|
// demo uses scissors to separete the four different rendering areas from | 
						|
// each other. | 
						|
// | 
						|
// (If the code seems a little bit strange here and there, it may be | 
						|
//  because I am not a friend of orthogonal projections) | 
						|
//======================================================================== | 
						|
 | 
						|
#define GLFW_INCLUDE_GLU | 
						|
#include <GLFW/glfw3.h> | 
						|
 | 
						|
#include <math.h> | 
						|
#include <stdio.h> | 
						|
#include <stdlib.h> | 
						|
 | 
						|
#ifndef M_PI | 
						|
#define M_PI 3.14159265358979323846 | 
						|
#endif | 
						|
 | 
						|
 | 
						|
//======================================================================== | 
						|
// Global variables | 
						|
//======================================================================== | 
						|
 | 
						|
// Mouse position | 
						|
static double xpos = 0, ypos = 0; | 
						|
 | 
						|
// Window size | 
						|
static int width, height; | 
						|
 | 
						|
// Active view: 0 = none, 1 = upper left, 2 = upper right, 3 = lower left, | 
						|
// 4 = lower right | 
						|
static int active_view = 0; | 
						|
 | 
						|
// Rotation around each axis | 
						|
static int rot_x = 0, rot_y = 0, rot_z = 0; | 
						|
 | 
						|
// Do redraw? | 
						|
static int do_redraw = 1; | 
						|
 | 
						|
 | 
						|
//======================================================================== | 
						|
// Draw a solid torus (use a display list for the model) | 
						|
//======================================================================== | 
						|
 | 
						|
#define TORUS_MAJOR     1.5 | 
						|
#define TORUS_MINOR     0.5 | 
						|
#define TORUS_MAJOR_RES 32 | 
						|
#define TORUS_MINOR_RES 32 | 
						|
 | 
						|
static void drawTorus(void) | 
						|
{ | 
						|
    static GLuint torus_list = 0; | 
						|
    int    i, j, k; | 
						|
    double s, t, x, y, z, nx, ny, nz, scale, twopi; | 
						|
 | 
						|
    if (!torus_list) | 
						|
    { | 
						|
        // Start recording displaylist | 
						|
        torus_list = glGenLists(1); | 
						|
        glNewList(torus_list, GL_COMPILE_AND_EXECUTE); | 
						|
 | 
						|
        // Draw torus | 
						|
        twopi = 2.0 * M_PI; | 
						|
        for (i = 0;  i < TORUS_MINOR_RES;  i++) | 
						|
        { | 
						|
            glBegin(GL_QUAD_STRIP); | 
						|
            for (j = 0;  j <= TORUS_MAJOR_RES;  j++) | 
						|
            { | 
						|
                for (k = 1;  k >= 0;  k--) | 
						|
                { | 
						|
                    s = (i + k) % TORUS_MINOR_RES + 0.5; | 
						|
                    t = j % TORUS_MAJOR_RES; | 
						|
 | 
						|
                    // Calculate point on surface | 
						|
                    x = (TORUS_MAJOR + TORUS_MINOR * cos(s * twopi / TORUS_MINOR_RES)) * cos(t * twopi / TORUS_MAJOR_RES); | 
						|
                    y = TORUS_MINOR * sin(s * twopi / TORUS_MINOR_RES); | 
						|
                    z = (TORUS_MAJOR + TORUS_MINOR * cos(s * twopi / TORUS_MINOR_RES)) * sin(t * twopi / TORUS_MAJOR_RES); | 
						|
 | 
						|
                    // Calculate surface normal | 
						|
                    nx = x - TORUS_MAJOR * cos(t * twopi / TORUS_MAJOR_RES); | 
						|
                    ny = y; | 
						|
                    nz = z - TORUS_MAJOR * sin(t * twopi / TORUS_MAJOR_RES); | 
						|
                    scale = 1.0 / sqrt(nx*nx + ny*ny + nz*nz); | 
						|
                    nx *= scale; | 
						|
                    ny *= scale; | 
						|
                    nz *= scale; | 
						|
 | 
						|
                    glNormal3f((float) nx, (float) ny, (float) nz); | 
						|
                    glVertex3f((float) x, (float) y, (float) z); | 
						|
                } | 
						|
            } | 
						|
 | 
						|
            glEnd(); | 
						|
        } | 
						|
 | 
						|
        // Stop recording displaylist | 
						|
        glEndList(); | 
						|
    } | 
						|
    else | 
						|
    { | 
						|
        // Playback displaylist | 
						|
        glCallList(torus_list); | 
						|
    } | 
						|
} | 
						|
 | 
						|
 | 
						|
//======================================================================== | 
						|
// Draw the scene (a rotating torus) | 
						|
//======================================================================== | 
						|
 | 
						|
static void drawScene(void) | 
						|
{ | 
						|
    const GLfloat model_diffuse[4]  = {1.0f, 0.8f, 0.8f, 1.0f}; | 
						|
    const GLfloat model_specular[4] = {0.6f, 0.6f, 0.6f, 1.0f}; | 
						|
    const GLfloat model_shininess   = 20.0f; | 
						|
 | 
						|
    glPushMatrix(); | 
						|
 | 
						|
    // Rotate the object | 
						|
    glRotatef((GLfloat) rot_x * 0.5f, 1.0f, 0.0f, 0.0f); | 
						|
    glRotatef((GLfloat) rot_y * 0.5f, 0.0f, 1.0f, 0.0f); | 
						|
    glRotatef((GLfloat) rot_z * 0.5f, 0.0f, 0.0f, 1.0f); | 
						|
 | 
						|
    // Set model color (used for orthogonal views, lighting disabled) | 
						|
    glColor4fv(model_diffuse); | 
						|
 | 
						|
    // Set model material (used for perspective view, lighting enabled) | 
						|
    glMaterialfv(GL_FRONT, GL_DIFFUSE, model_diffuse); | 
						|
    glMaterialfv(GL_FRONT, GL_SPECULAR, model_specular); | 
						|
    glMaterialf(GL_FRONT, GL_SHININESS, model_shininess); | 
						|
 | 
						|
    // Draw torus | 
						|
    drawTorus(); | 
						|
 | 
						|
    glPopMatrix(); | 
						|
} | 
						|
 | 
						|
 | 
						|
//======================================================================== | 
						|
// Draw a 2D grid (used for orthogonal views) | 
						|
//======================================================================== | 
						|
 | 
						|
static void drawGrid(float scale, int steps) | 
						|
{ | 
						|
    int i; | 
						|
    float x, y; | 
						|
 | 
						|
    glPushMatrix(); | 
						|
 | 
						|
    // Set background to some dark bluish grey | 
						|
    glClearColor(0.05f, 0.05f, 0.2f, 0.0f); | 
						|
    glClear(GL_COLOR_BUFFER_BIT); | 
						|
 | 
						|
    // Setup modelview matrix (flat XY view) | 
						|
    glLoadIdentity(); | 
						|
    gluLookAt(0.0, 0.0, 1.0, | 
						|
              0.0, 0.0, 0.0, | 
						|
              0.0, 1.0, 0.0); | 
						|
 | 
						|
    // We don't want to update the Z-buffer | 
						|
    glDepthMask(GL_FALSE); | 
						|
 | 
						|
    // Set grid color | 
						|
    glColor3f(0.0f, 0.5f, 0.5f); | 
						|
 | 
						|
    glBegin(GL_LINES); | 
						|
 | 
						|
    // Horizontal lines | 
						|
    x = scale * 0.5f * (float) (steps - 1); | 
						|
    y = -scale * 0.5f * (float) (steps - 1); | 
						|
    for (i = 0;  i < steps;  i++) | 
						|
    { | 
						|
        glVertex3f(-x, y, 0.0f); | 
						|
        glVertex3f(x, y, 0.0f); | 
						|
        y += scale; | 
						|
    } | 
						|
 | 
						|
    // Vertical lines | 
						|
    x = -scale * 0.5f * (float) (steps - 1); | 
						|
    y = scale * 0.5f * (float) (steps - 1); | 
						|
    for (i = 0;  i < steps;  i++) | 
						|
    { | 
						|
        glVertex3f(x, -y, 0.0f); | 
						|
        glVertex3f(x, y, 0.0f); | 
						|
        x += scale; | 
						|
    } | 
						|
 | 
						|
    glEnd(); | 
						|
 | 
						|
    // Enable Z-buffer writing again | 
						|
    glDepthMask(GL_TRUE); | 
						|
 | 
						|
    glPopMatrix(); | 
						|
} | 
						|
 | 
						|
 | 
						|
//======================================================================== | 
						|
// Draw all views | 
						|
//======================================================================== | 
						|
 | 
						|
static void drawAllViews(void) | 
						|
{ | 
						|
    const GLfloat light_position[4] = {0.0f, 8.0f, 8.0f, 1.0f}; | 
						|
    const GLfloat light_diffuse[4]  = {1.0f, 1.0f, 1.0f, 1.0f}; | 
						|
    const GLfloat light_specular[4] = {1.0f, 1.0f, 1.0f, 1.0f}; | 
						|
    const GLfloat light_ambient[4]  = {0.2f, 0.2f, 0.3f, 1.0f}; | 
						|
    double aspect; | 
						|
 | 
						|
    // Calculate aspect of window | 
						|
    if (height > 0) | 
						|
        aspect = (double) width / (double) height; | 
						|
    else | 
						|
        aspect = 1.0; | 
						|
 | 
						|
    // Clear screen | 
						|
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | 
						|
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 
						|
 | 
						|
    // Enable scissor test | 
						|
    glEnable(GL_SCISSOR_TEST); | 
						|
 | 
						|
    // Enable depth test | 
						|
    glEnable(GL_DEPTH_TEST); | 
						|
    glDepthFunc(GL_LEQUAL); | 
						|
 | 
						|
    // ** ORTHOGONAL VIEWS ** | 
						|
 | 
						|
    // For orthogonal views, use wireframe rendering | 
						|
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | 
						|
 | 
						|
    // Enable line anti-aliasing | 
						|
    glEnable(GL_LINE_SMOOTH); | 
						|
    glEnable(GL_BLEND); | 
						|
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
						|
 | 
						|
    // Setup orthogonal projection matrix | 
						|
    glMatrixMode(GL_PROJECTION); | 
						|
    glLoadIdentity(); | 
						|
    glOrtho(-3.0 * aspect, 3.0 * aspect, -3.0, 3.0, 1.0, 50.0); | 
						|
 | 
						|
    // Upper left view (TOP VIEW) | 
						|
    glViewport(0, height / 2, width / 2, height / 2); | 
						|
    glScissor(0, height / 2, width / 2, height / 2); | 
						|
    glMatrixMode(GL_MODELVIEW); | 
						|
    glLoadIdentity(); | 
						|
    gluLookAt(0.0f, 10.0f, 1e-3f,   // Eye-position (above) | 
						|
              0.0f, 0.0f, 0.0f,     // View-point | 
						|
              0.0f, 1.0f, 0.0f);   // Up-vector | 
						|
    drawGrid(0.5, 12); | 
						|
    drawScene(); | 
						|
 | 
						|
    // Lower left view (FRONT VIEW) | 
						|
    glViewport(0, 0, width / 2, height / 2); | 
						|
    glScissor(0, 0, width / 2, height / 2); | 
						|
    glMatrixMode(GL_MODELVIEW); | 
						|
    glLoadIdentity(); | 
						|
    gluLookAt(0.0f, 0.0f, 10.0f,    // Eye-position (in front of) | 
						|
              0.0f, 0.0f, 0.0f,     // View-point | 
						|
              0.0f, 1.0f, 0.0f);   // Up-vector | 
						|
    drawGrid(0.5, 12); | 
						|
    drawScene(); | 
						|
 | 
						|
    // Lower right view (SIDE VIEW) | 
						|
    glViewport(width / 2, 0, width / 2, height / 2); | 
						|
    glScissor(width / 2, 0, width / 2, height / 2); | 
						|
    glMatrixMode(GL_MODELVIEW); | 
						|
    glLoadIdentity(); | 
						|
    gluLookAt(10.0f, 0.0f, 0.0f,    // Eye-position (to the right) | 
						|
              0.0f, 0.0f, 0.0f,     // View-point | 
						|
              0.0f, 1.0f, 0.0f);   // Up-vector | 
						|
    drawGrid(0.5, 12); | 
						|
    drawScene(); | 
						|
 | 
						|
    // Disable line anti-aliasing | 
						|
    glDisable(GL_LINE_SMOOTH); | 
						|
    glDisable(GL_BLEND); | 
						|
 | 
						|
    // ** PERSPECTIVE VIEW ** | 
						|
 | 
						|
    // For perspective view, use solid rendering | 
						|
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | 
						|
 | 
						|
    // Enable face culling (faster rendering) | 
						|
    glEnable(GL_CULL_FACE); | 
						|
    glCullFace(GL_BACK); | 
						|
    glFrontFace(GL_CW); | 
						|
 | 
						|
    // Setup perspective projection matrix | 
						|
    glMatrixMode(GL_PROJECTION); | 
						|
    glLoadIdentity(); | 
						|
    gluPerspective(65.0f, aspect, 1.0f, 50.0f); | 
						|
 | 
						|
    // Upper right view (PERSPECTIVE VIEW) | 
						|
    glViewport(width / 2, height / 2, width / 2, height / 2); | 
						|
    glScissor(width / 2, height / 2, width / 2, height / 2); | 
						|
    glMatrixMode(GL_MODELVIEW); | 
						|
    glLoadIdentity(); | 
						|
    gluLookAt(3.0f, 1.5f, 3.0f,     // Eye-position | 
						|
              0.0f, 0.0f, 0.0f,     // View-point | 
						|
              0.0f, 1.0f, 0.0f);   // Up-vector | 
						|
 | 
						|
    // Configure and enable light source 1 | 
						|
    glLightfv(GL_LIGHT1, GL_POSITION, light_position); | 
						|
    glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); | 
						|
    glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); | 
						|
    glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); | 
						|
    glEnable(GL_LIGHT1); | 
						|
    glEnable(GL_LIGHTING); | 
						|
 | 
						|
    // Draw scene | 
						|
    drawScene(); | 
						|
 | 
						|
    // Disable lighting | 
						|
    glDisable(GL_LIGHTING); | 
						|
 | 
						|
    // Disable face culling | 
						|
    glDisable(GL_CULL_FACE); | 
						|
 | 
						|
    // Disable depth test | 
						|
    glDisable(GL_DEPTH_TEST); | 
						|
 | 
						|
    // Disable scissor test | 
						|
    glDisable(GL_SCISSOR_TEST); | 
						|
 | 
						|
    // Draw a border around the active view | 
						|
    if (active_view > 0 && active_view != 2) | 
						|
    { | 
						|
        glViewport(0, 0, width, height); | 
						|
 | 
						|
        glMatrixMode(GL_PROJECTION); | 
						|
        glLoadIdentity(); | 
						|
        glOrtho(0.0, 2.0, 0.0, 2.0, 0.0, 1.0); | 
						|
 | 
						|
        glMatrixMode(GL_MODELVIEW); | 
						|
        glLoadIdentity(); | 
						|
        glTranslatef((GLfloat) ((active_view - 1) & 1), (GLfloat) (1 - (active_view - 1) / 2), 0.0f); | 
						|
 | 
						|
        glColor3f(1.0f, 1.0f, 0.6f); | 
						|
 | 
						|
        glBegin(GL_LINE_STRIP); | 
						|
        glVertex2i(0, 0); | 
						|
        glVertex2i(1, 0); | 
						|
        glVertex2i(1, 1); | 
						|
        glVertex2i(0, 1); | 
						|
        glVertex2i(0, 0); | 
						|
        glEnd(); | 
						|
    } | 
						|
} | 
						|
 | 
						|
 | 
						|
//======================================================================== | 
						|
// Framebuffer size callback function | 
						|
//======================================================================== | 
						|
 | 
						|
static void framebufferSizeFun(GLFWwindow* window, int w, int h) | 
						|
{ | 
						|
    width  = w; | 
						|
    height = h > 0 ? h : 1; | 
						|
    do_redraw = 1; | 
						|
} | 
						|
 | 
						|
 | 
						|
//======================================================================== | 
						|
// Window refresh callback function | 
						|
//======================================================================== | 
						|
 | 
						|
static void windowRefreshFun(GLFWwindow* window) | 
						|
{ | 
						|
    do_redraw = 1; | 
						|
} | 
						|
 | 
						|
 | 
						|
//======================================================================== | 
						|
// Mouse position callback function | 
						|
//======================================================================== | 
						|
 | 
						|
static void cursorPosFun(GLFWwindow* window, double x, double y) | 
						|
{ | 
						|
    // Depending on which view was selected, rotate around different axes | 
						|
    switch (active_view) | 
						|
    { | 
						|
        case 1: | 
						|
            rot_x += (int) (y - ypos); | 
						|
            rot_z += (int) (x - xpos); | 
						|
            do_redraw = 1; | 
						|
            break; | 
						|
        case 3: | 
						|
            rot_x += (int) (y - ypos); | 
						|
            rot_y += (int) (x - xpos); | 
						|
            do_redraw = 1; | 
						|
            break; | 
						|
        case 4: | 
						|
            rot_y += (int) (x - xpos); | 
						|
            rot_z += (int) (y - ypos); | 
						|
            do_redraw = 1; | 
						|
            break; | 
						|
        default: | 
						|
            // Do nothing for perspective view, or if no view is selected | 
						|
            break; | 
						|
    } | 
						|
 | 
						|
    // Remember cursor position | 
						|
    xpos = x; | 
						|
    ypos = y; | 
						|
} | 
						|
 | 
						|
 | 
						|
//======================================================================== | 
						|
// Mouse button callback function | 
						|
//======================================================================== | 
						|
 | 
						|
static void mouseButtonFun(GLFWwindow* window, int button, int action, int mods) | 
						|
{ | 
						|
    if ((button == GLFW_MOUSE_BUTTON_LEFT) && action == GLFW_PRESS) | 
						|
    { | 
						|
        // Detect which of the four views was clicked | 
						|
        active_view = 1; | 
						|
        if (xpos >= width / 2) | 
						|
            active_view += 1; | 
						|
        if (ypos >= height / 2) | 
						|
            active_view += 2; | 
						|
    } | 
						|
    else if (button == GLFW_MOUSE_BUTTON_LEFT) | 
						|
    { | 
						|
        // Deselect any previously selected view | 
						|
        active_view = 0; | 
						|
    } | 
						|
 | 
						|
    do_redraw = 1; | 
						|
} | 
						|
 | 
						|
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) | 
						|
{ | 
						|
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) | 
						|
        glfwSetWindowShouldClose(window, GL_TRUE); | 
						|
} | 
						|
 | 
						|
 | 
						|
//======================================================================== | 
						|
// main | 
						|
//======================================================================== | 
						|
 | 
						|
int main(void) | 
						|
{ | 
						|
    GLFWwindow* window; | 
						|
 | 
						|
    // Initialise GLFW | 
						|
    if (!glfwInit()) | 
						|
    { | 
						|
        fprintf(stderr, "Failed to initialize GLFW\n"); | 
						|
        exit(EXIT_FAILURE); | 
						|
    } | 
						|
 | 
						|
    // Open OpenGL window | 
						|
    window = glfwCreateWindow(500, 500, "Split view demo", NULL, NULL); | 
						|
    if (!window) | 
						|
    { | 
						|
        fprintf(stderr, "Failed to open GLFW window\n"); | 
						|
 | 
						|
        glfwTerminate(); | 
						|
        exit(EXIT_FAILURE); | 
						|
    } | 
						|
 | 
						|
    // Set callback functions | 
						|
    glfwSetFramebufferSizeCallback(window, framebufferSizeFun); | 
						|
    glfwSetWindowRefreshCallback(window, windowRefreshFun); | 
						|
    glfwSetCursorPosCallback(window, cursorPosFun); | 
						|
    glfwSetMouseButtonCallback(window, mouseButtonFun); | 
						|
    glfwSetKeyCallback(window, key_callback); | 
						|
 | 
						|
    // Enable vsync | 
						|
    glfwMakeContextCurrent(window); | 
						|
    glfwSwapInterval(1); | 
						|
 | 
						|
    glfwGetFramebufferSize(window, &width, &height); | 
						|
    framebufferSizeFun(window, width, height); | 
						|
 | 
						|
    // Main loop | 
						|
    for (;;) | 
						|
    { | 
						|
        // Only redraw if we need to | 
						|
        if (do_redraw) | 
						|
        { | 
						|
            // Draw all views | 
						|
            drawAllViews(); | 
						|
 | 
						|
            // Swap buffers | 
						|
            glfwSwapBuffers(window); | 
						|
 | 
						|
            do_redraw = 0; | 
						|
        } | 
						|
 | 
						|
        // Wait for new events | 
						|
        glfwWaitEvents(); | 
						|
 | 
						|
        // Check if the window should be closed | 
						|
        if (glfwWindowShouldClose(window)) | 
						|
            break; | 
						|
    } | 
						|
 | 
						|
    // Close OpenGL window and terminate GLFW | 
						|
    glfwTerminate(); | 
						|
 | 
						|
    exit(EXIT_SUCCESS); | 
						|
} | 
						|
 | 
						|
 |