📄 opengl_renderer.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: opengl_renderer.cpp,v $ * PRODUCTION Revision 1000.3 2004/06/01 18:28:52 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.79 * PRODUCTION * =========================================================================== *//* $Id: opengl_renderer.cpp,v 1000.3 2004/06/01 18:28:52 gouriano Exp $* ===========================================================================** PUBLIC DOMAIN NOTICE* National Center for Biotechnology Information** This software/database is a "United States Government Work" under the* terms of the United States Copyright Act. It was written as part of* the author's official duties as a United States Government employee and* thus cannot be copyrighted. This software/database is freely available* to the public for use. The National Library of Medicine and the U.S.* Government have not placed any restriction on its use or reproduction.** Although all reasonable efforts have been taken to ensure the accuracy* and reliability of the software and data, the NLM and the U.S.* Government do not and cannot warrant the performance or results that* may be obtained by using this software or data. The NLM and the U.S.* Government disclaim all warranties, express or implied, including* warranties of performance, merchantability or fitness for any particular* purpose.** Please cite the author in any work or product based on this material.** ===========================================================================** Authors: Paul Thiessen** File Description:* Classes to hold the OpenGL rendering engine** ===========================================================================*/#ifdef _MSC_VER#pragma warning(disable:4018) // disable signed/unsigned mismatch warning in MSVC#endif#include <ncbi_pch.hpp>#include <corelib/ncbistd.hpp>#include <corelib/ncbitime.hpp> // avoids some 'CurrentTime' conflict later on...#include <corelib/ncbiobj.hpp>#if defined(__WXMSW__)#include <windows.h>#include <GL/gl.h>#include <GL/glu.h>#elif defined(__WXGTK__)#include <GL/gl.h>#include <GL/glu.h>#include <GL/glx.h>#include <gdk/gdk.h> // needed for GdkFont#elif defined(__WXMAC__)//#include <Fonts.h>#include <OpenGL/gl.h>#include <OpenGL/glu.h>#endif#include <math.h>#include <stdlib.h> // for rand, srand#include <objects/cn3d/Cn3d_GL_matrix.hpp>#include <objects/cn3d/Cn3d_vector.hpp>#include "opengl_renderer.hpp"#include "structure_window.hpp"#include "cn3d_glcanvas.hpp"#include "structure_set.hpp"#include "style_manager.hpp"#include "messenger.hpp"#include "cn3d_tools.hpp"#include "asn_converter.hpp"#include "cn3d_colors.hpp"USING_NCBI_SCOPE;USING_SCOPE(objects);BEGIN_SCOPE(Cn3D)static const double PI = acos(-1.0);static inline double DegreesToRad(double deg) { return deg*PI/180.0; }static inline double RadToDegrees(double rad) { return rad*180.0/PI; }const unsigned int OpenGLRenderer::NO_LIST = 0;const unsigned int OpenGLRenderer::FIRST_LIST = 1;const unsigned int OpenGLRenderer::FONT_BASE = 1000;static const unsigned int ALL_FRAMES = 4294967295;// it's easier to keep one global qobj for nowstatic GLUquadricObj *qobj = NULL;// pick bufferconst unsigned int OpenGLRenderer::NO_NAME = 0;static const int pickBufSize = 1024;static GLuint selectBuf[pickBufSize];/* these are used for both matrial colors and light colors */static const GLfloat Color_Off[4] = { 0.0f, 0.0f, 0.0f, 1.0f };static const GLfloat Color_MostlyOff[4] = { 0.05f, 0.05f, 0.05f, 1.0f };static const GLfloat Color_MostlyOn[4] = { 0.95f, 0.95f, 0.95f, 1.0f };static const GLfloat Color_On[4] = { 1.0f, 1.0f, 1.0f, 1.0f };static const GLfloat Color_Specular[4] = { 0.5f, 0.5f, 0.5f, 1.0f };static const GLint Shininess = 40;// to cache registry valuesstatic int atomSlices, atomStacks, bondSides, wormSides, wormSegments, helixSides;static bool highlightsOn;static string projectionType;// matrix conversion utility functions// convert from Matrix to GL-matrix orderingstatic void Matrix2GL(const Matrix& m, GLdouble *g){ g[0]=m.m[0]; g[4]=m.m[1]; g[8]=m.m[2]; g[12]=m.m[3]; g[1]=m.m[4]; g[5]=m.m[5]; g[9]=m.m[6]; g[13]=m.m[7]; g[2]=m.m[8]; g[6]=m.m[9]; g[10]=m.m[10]; g[14]=m.m[11]; g[3]=m.m[12]; g[7]=m.m[13]; g[11]=m.m[14]; g[15]=m.m[15];}// convert from GL-matrix to Matrix orderingstatic void GL2Matrix(GLdouble *g, Matrix *m){ m->m[0]=g[0]; m->m[1]=g[4]; m->m[2]=g[8]; m->m[3]=g[12]; m->m[4]=g[1]; m->m[5]=g[5]; m->m[6]=g[9]; m->m[7]=g[13]; m->m[8]=g[2]; m->m[9]=g[6]; m->m[10]=g[10]; m->m[11]=g[14]; m->m[12]=g[3]; m->m[13]=g[7]; m->m[14]=g[11]; m->m[15]=g[15];}// OpenGLRenderer methods - initialization and setupOpenGLRenderer::OpenGLRenderer(Cn3DGLCanvas *parentGLCanvas) : structureSet(NULL), glCanvas(parentGLCanvas), selectMode(false), currentDisplayList(NO_LIST), cameraAngleRad(0.0), rotateSpeed(0.5), stereoOn(false){ // make sure a name will fit in a GLuint if (sizeof(GLuint) < sizeof(unsigned int)) FATALMSG("Cn3D requires that sizeof(GLuint) >= sizeof(unsigned int)");}void OpenGLRenderer::Init(void) const{ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // set up the lighting // directional light (faster) when LightPosition[4] == 0.0 GLfloat LightPosition[4] = { 0.0f, 0.0f, 1.0f, 0.0f }; glLightfv(GL_LIGHT0, GL_POSITION, LightPosition); glLightfv(GL_LIGHT0, GL_AMBIENT, Color_Off); glLightfv(GL_LIGHT0, GL_DIFFUSE, Color_MostlyOn); glLightfv(GL_LIGHT0, GL_SPECULAR, Color_On); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Color_On); // global ambience glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); // set these material colors glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Color_Off); glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, Shininess); // turn on culling to speed rendering glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glFrontFace(GL_CCW); // misc options glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glDisable(GL_NORMALIZE); glDisable(GL_SCISSOR_TEST); RecreateQuadric();}// methods dealing with the viewvoid OpenGLRenderer::NewView(double eyeTranslateToAngleDegrees) const{ if (cameraAngleRad <= 0.0) return; GLint Viewport[4]; glGetIntegerv(GL_VIEWPORT, Viewport); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (selectMode) { gluPickMatrix(static_cast<GLdouble>(selectX), static_cast<GLdouble>(Viewport[3] - selectY), 1.0, 1.0, Viewport); } GLdouble aspect = (static_cast<GLdouble>(Viewport[2])) / Viewport[3]; // set camera angle/perspective if (projectionType == "Perspective") { gluPerspective(RadToDegrees(cameraAngleRad), // viewing angle (degrees) aspect, // w/h aspect cameraClipNear, // near clipping plane cameraClipFar); // far clipping plane } else { // Orthographic GLdouble right, top; top = ((cameraClipNear + cameraClipFar) / 2.0) * sin(cameraAngleRad / 2.0); right = top * aspect; glOrtho(-right, // sides of viewing box, assuming eye is at (0,0,0) right, -top, top, cameraClipNear, // near clipping plane cameraClipFar); // far clipping plane } Vector cameraLoc(0.0, 0.0, cameraDistance); if (stereoOn && eyeTranslateToAngleDegrees != 0.0) { Vector view(cameraLookAtX, cameraLookAtY, -cameraDistance); Vector translate = vector_cross(view, Vector(0.0, 1.0, 0.0)); translate.normalize(); translate *= view.length() * tan(DegreesToRad(eyeTranslateToAngleDegrees)); cameraLoc += translate; } // set camera position and direction gluLookAt(cameraLoc.x, cameraLoc.y, cameraLoc.z, // the camera position cameraLookAtX, cameraLookAtY, 0.0, // the "look-at" point 0.0, 1.0, 0.0); // the up direction glMatrixMode(GL_MODELVIEW);}void OpenGLRenderer::Display(void){ if (structureSet) { const Vector& background = structureSet->styleManager->GetBackgroundColor(); glClearColor(background[0], background[1], background[2], 1.0); } else glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (selectMode) { glInitNames(); glPushName(0); } GLint viewport[4] = {0, 0, 0, 0}; double eyeSeparationDegrees = 0.0; if (stereoOn) { bool proximalStereo; glGetIntegerv(GL_VIEWPORT, viewport); if (!RegistryGetDouble(REG_ADVANCED_SECTION, REG_STEREO_SEPARATION, &eyeSeparationDegrees) || !RegistryGetBoolean(REG_ADVANCED_SECTION, REG_PROXIMAL_STEREO, &proximalStereo)) { ERRORMSG("OpenGLRenderer::Display() - error getting stereo settings from registry"); return; } if (!proximalStereo) eyeSeparationDegrees = -eyeSeparationDegrees; } int first = 1, last = stereoOn ? 2 : 1; for (int e=first; e<=last; ++e) { glLoadMatrixd(viewMatrix); // adjust viewport & camera angle for stereo if (stereoOn) { if (e == first) { // left side glViewport(0, viewport[1], viewport[2] / 2, viewport[3]); NewView(eyeSeparationDegrees / 2); } else { // right side glViewport(viewport[2] / 2, viewport[1], viewport[2] - viewport[2] / 2, viewport[3]); NewView(-eyeSeparationDegrees / 2); } } if (structureSet) { if (currentFrame == ALL_FRAMES) { for (unsigned int i=FIRST_LIST; i<=structureSet->lastDisplayList; ++i) { PushMatrix(*(structureSet->transformMap[i])); glCallList(i); PopMatrix(); AddTransparentSpheresForList(i); } } else { StructureSet::DisplayLists::const_iterator l, le=structureSet->frameMap[currentFrame].end(); for (l=structureSet->frameMap[currentFrame].begin(); l!=le; ++l) { PushMatrix(*(structureSet->transformMap[*l])); glCallList(*l); PopMatrix(); AddTransparentSpheresForList(*l); } } // draw transparent spheres, which are already stored in view-transformed coordinates glLoadIdentity(); RenderTransparentSpheres(); } // draw logo if no structure else { glCallList(FIRST_LIST); } } glFlush(); // restore full viewport if (stereoOn) glViewport(0, viewport[1], viewport[2], viewport[3]);}void OpenGLRenderer::EnableStereo(bool enableStereo){ TRACEMSG("turning " << (enableStereo ? "on" : "off" ) << " stereo"); stereoOn = enableStereo; if (!stereoOn) NewView();}void OpenGLRenderer::ResetCamera(void){ // set up initial camera glLoadIdentity(); cameraLookAtX = cameraLookAtY = 0.0; if (structureSet) { // for structure cameraAngleRad = DegreesToRad(35.0); // calculate camera distance so that structure fits exactly in // the window in any rotation (based on structureSet's maxDistFromCenter) GLint Viewport[4]; glGetIntegerv(GL_VIEWPORT, Viewport); double angle = cameraAngleRad, aspect = (static_cast<double>(Viewport[2])) / Viewport[3]; if (aspect < 1.0) angle *= aspect; cameraDistance = structureSet->maxDistFromCenter / sin(angle/2); // allow a little "extra" room between clipping planes cameraClipNear = (cameraDistance - structureSet->maxDistFromCenter) * 0.66; cameraClipFar = (cameraDistance + structureSet->maxDistFromCenter) * 1.2; // move structureSet's center to origin glTranslated(-structureSet->center.x, -structureSet->center.y, -structureSet->center.z); structureSet->rotationCenter = structureSet->center; } else { // for logo cameraAngleRad = PI / 14; cameraDistance = 200; cameraClipNear = 0.5*cameraDistance; cameraClipFar = 1.5*cameraDistance; } // reset matrix glGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix); NewView();}void OpenGLRenderer::ChangeView(eViewAdjust control, int dX, int dY, int X2, int Y2){ bool doTranslation = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -