/* * Copyright 2011-2013 Blender Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "util/opengl.h" #include "util/string.h" #include "util/time.h" #include "util/version.h" #include "util/view.h" #ifdef __APPLE__ # include #else # include #endif CCL_NAMESPACE_BEGIN /* structs */ struct View { ViewInitFunc initf; ViewExitFunc exitf; ViewResizeFunc resize; ViewDisplayFunc display; ViewKeyboardFunc keyboard; ViewMotionFunc motion; bool first_display; bool redraw; int mouseX, mouseY; int mouseBut0, mouseBut2; int width, height; } V; /* public */ static void view_display_text(int x, int y, const char *text) { const char *c; glRasterPos3f(x, y, 0); for (c = text; *c != '\0'; c++) glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, *c); } void view_display_info(const char *info) { const int height = 20; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(0.1f, 0.1f, 0.1f, 0.8f); glRectf(0.0f, V.height - height, V.width, V.height); glDisable(GL_BLEND); glColor3f(0.5f, 0.5f, 0.5f); view_display_text(10, 7 + V.height - height, info); glColor3f(1.0f, 1.0f, 1.0f); } void view_display_help() { const int w = (int)((float)V.width / 1.15f); const int h = (int)((float)V.height / 1.15f); const int x1 = (V.width - w) / 2; const int x2 = x1 + w; const int y1 = (V.height - h) / 2; const int y2 = y1 + h; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(0.5f, 0.5f, 0.5f, 0.8f); glRectf(x1, y1, x2, y2); glDisable(GL_BLEND); glColor3f(0.8f, 0.8f, 0.8f); string info = string("Cycles Renderer ") + CYCLES_VERSION_STRING; view_display_text(x1 + 20, y2 - 20, info.c_str()); view_display_text(x1 + 20, y2 - 40, "(C) 2011-2016 Blender Foundation"); view_display_text(x1 + 20, y2 - 80, "Controls:"); view_display_text(x1 + 20, y2 - 100, "h: Info/Help"); view_display_text(x1 + 20, y2 - 120, "r: Reset"); view_display_text(x1 + 20, y2 - 140, "p: Pause"); view_display_text(x1 + 20, y2 - 160, "esc: Cancel"); view_display_text(x1 + 20, y2 - 180, "q: Quit program"); view_display_text(x1 + 20, y2 - 210, "i: Interactive mode"); view_display_text(x1 + 20, y2 - 230, "Left mouse: Move camera"); view_display_text(x1 + 20, y2 - 250, "Right mouse: Rotate camera"); view_display_text(x1 + 20, y2 - 270, "W/A/S/D: Move camera"); view_display_text(x1 + 20, y2 - 290, "0/1/2/3: Set max bounces"); glColor3f(1.0f, 1.0f, 1.0f); } static void view_display() { if (V.first_display) { if (V.initf) V.initf(); if (V.exitf) atexit(V.exitf); V.first_display = false; } glClearColor(0.05f, 0.05f, 0.05f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, V.width, 0, V.height, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRasterPos3f(0, 0, 0); if (V.display) V.display(); glutSwapBuffers(); } static void view_reshape(int width, int height) { if (width <= 0 || height <= 0) return; V.width = width; V.height = height; glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if (V.resize) V.resize(width, height); } static void view_keyboard(unsigned char key, int x, int y) { if (V.keyboard) V.keyboard(key); if (key == 'm') printf("mouse %d %d\n", x, y); if (key == 'q') { if (V.exitf) V.exitf(); exit(0); } } static void view_mouse(int button, int state, int x, int y) { if (button == 0) { if (state == GLUT_DOWN) { V.mouseX = x; V.mouseY = y; V.mouseBut0 = 1; } else if (state == GLUT_UP) { V.mouseBut0 = 0; } } else if (button == 2) { if (state == GLUT_DOWN) { V.mouseX = x; V.mouseY = y; V.mouseBut2 = 1; } else if (state == GLUT_UP) { V.mouseBut2 = 0; } } } static void view_motion(int x, int y) { const int but = V.mouseBut0 ? 0 : 2; const int distX = x - V.mouseX; const int distY = y - V.mouseY; if (V.motion) V.motion(distX, distY, but); V.mouseX = x; V.mouseY = y; } static void view_idle() { if (V.redraw) { V.redraw = false; glutPostRedisplay(); } time_sleep(0.1); } void view_main_loop(const char *title, int width, int height, ViewInitFunc initf, ViewExitFunc exitf, ViewResizeFunc resize, ViewDisplayFunc display, ViewKeyboardFunc keyboard, ViewMotionFunc motion) { const char *name = "app"; char *argv = (char *)name; int argc = 1; memset(&V, 0, sizeof(V)); V.width = width; V.height = height; V.first_display = true; V.redraw = false; V.initf = initf; V.exitf = exitf; V.resize = resize; V.display = display; V.keyboard = keyboard; V.motion = motion; glutInit(&argc, &argv); glutInitWindowSize(width, height); glutInitWindowPosition(0, 0); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow(title); glewInit(); view_reshape(width, height); glutDisplayFunc(view_display); glutIdleFunc(view_idle); glutReshapeFunc(view_reshape); glutKeyboardFunc(view_keyboard); glutMouseFunc(view_mouse); glutMotionFunc(view_motion); glutMainLoop(); } void view_redraw() { V.redraw = true; } CCL_NAMESPACE_END