layer2/RepSphereImmediate.cpp (265 lines of code) (raw):

/* A* ------------------------------------------------------------------- B* This file contains source code for the PyMOL computer program C* Copyright (c) Schrodinger, LLC. D* ------------------------------------------------------------------- E* It is unlawful to modify or remove this copyright notice. F* ------------------------------------------------------------------- G* Please see the accompanying LICENSE file for further information. H* ------------------------------------------------------------------- I* Additional authors of this source file include: -* -* -* Z* ------------------------------------------------------------------- */ #include "RepSphere.h" #include "RepSphereImmediate.h" #include "ShaderMgr.h" #include "Sphere.h" #ifndef PURE_OPENGL_ES_2 extern CShaderPrg *sphereARBShaderPrg; #ifdef _PYMOL_ARB_SHADERS static void RepSphereRenderOneSphere_ARB(PyMOLGlobals *G, RenderInfo *info, const float *color, float *last_radius, float *cur_radius, const float *fog_info, const float *v) { static const float _00[2] = {0.0F, 0.0F}; static const float _01[2] = {0.0F, 1.0F}; static const float _11[2] = {1.0F, 1.0F}; static const float _10[2] = {1.0F, 0.0F}; float v3 = v[3]; if ((*last_radius) != ((*cur_radius) = v3)) { glEnd(); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 0, 0.0F, 0.0F, v3, 0.0F); glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, fog_info[0], fog_info[1], 0.0F, 0.0F); glBegin(GL_QUADS); (*last_radius) = (*cur_radius); } glColor3fv(color); glTexCoord2fv(_00); glVertex3fv(v); glTexCoord2fv(_10); glVertex3fv(v); glTexCoord2fv(_11); glVertex3fv(v); glTexCoord2fv(_01); glVertex3fv(v); } static void RenderSphereMode_Immediate_5(PyMOLGlobals *G, RenderInfo *info, CoordSet *cs, ObjectMolecule *obj, int *repActive, float sphere_scale) { if (!sphereARBShaderPrg) { sphereARBShaderPrg = CShaderPrg::NewARB( G, "sphere_arb", G->ShaderMgr->GetShaderSource("sphere_arb_vs.vs"), G->ShaderMgr->GetShaderSource("sphere_arb_fs.fs")); } if (sphereARBShaderPrg) { float fog_info[3]; RenderSphereComputeFog(G, info, fog_info); G->ShaderMgr->Enable_SphereShaderARB(); glNormal3fv(info->view_normal); glBegin(GL_QUADS); { float last_radius = -1.0F, cur_radius; int a; int nIndex = cs->NIndex; AtomInfoType *atomInfo = obj->AtomInfo; int *i2a = cs->IdxToAtm; float *v = cs->Coord; for (a = 0; a < nIndex; a++) { AtomInfoType *ai = atomInfo + *(i2a++); if (GET_BIT(ai->visRep, cRepSphere)) { float vr[4]; copy3f(v, vr); vr[3] = ai->vdw * sphere_scale; (*repActive) = true; RepSphereRenderOneSphere_ARB(G, info, ColorGet(G, ai->color), &last_radius, &cur_radius, fog_info, vr); } v += 3; } glEnd(); } sphereARBShaderPrg->DisableARB(); } } #endif static void RenderSphereMode_Immediate_Triangles(PyMOLGlobals *G, CoordSet *cs, ObjectMolecule *obj, int *repActive, float sphere_scale) { /* triangle-based spheres */ int ds = SettingGet_i(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_quality); if (ds < 0) ds = 0; if (ds > 4) ds = 4; SphereRec *sp = G->Sphere->Sphere[ds]; { int a; int nIndex = cs->NIndex; AtomInfoType *atomInfo = obj->AtomInfo; int *i2a = cs->IdxToAtm; int last_color = -1; float *v = cs->Coord; int *sp_Sequence = sp->Sequence; int *sp_StripLen = sp->StripLen; int sp_NStrip = sp->NStrip; Vector3f *sp_dot = sp->dot; for (a = 0; a < nIndex; a++) { AtomInfoType *ai = atomInfo + *(i2a++); if (GET_BIT(ai->visRep, cRepSphere)) { float vdw = ai->vdw * sphere_scale; int c = ai->color; float v0 = v[0]; float v1 = v[1]; float v2 = v[2]; (*repActive) = true; if (c != last_color) { last_color = c; glColor3fv(ColorGet(G, c)); } { int *s = sp_StripLen; int *q = sp_Sequence; int b; for (b = 0; b < sp_NStrip; b++) { int nc = *(s++); glBegin(GL_TRIANGLE_STRIP); for (c = 0; c < nc; c++) { float *sp_dot_q = &sp_dot[*(q++)][0]; glNormal3fv(sp_dot_q); /* normal */ glVertex3f(v0 + vdw * sp_dot_q[0], v1 + vdw * sp_dot_q[1], v2 + vdw * sp_dot_q[2]); } glEnd(); } } } v += 3; } } } static void RenderSphereMode_Immediate_1_2_3(PyMOLGlobals *G, RenderInfo *info, CoordSet *cs, ObjectMolecule *obj, int *repActive, float pixel_scale, int sphere_mode) { /* sphere_mode is 1, 2, or 3 */ float max_radius = SettingGet_f(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_point_max_size) * 3 * pixel_scale; int clamp_size_flag = (max_radius >= 0.0F); int a; int nIndex = cs->NIndex; AtomInfoType *atomInfo = obj->AtomInfo; int *i2a = cs->IdxToAtm; int last_color = -1; float *v = cs->Coord; float last_radius = -1.0F; if (!info->line_lighting) glDisable(GL_LIGHTING); glBegin(GL_POINTS); for (a = 0; a < nIndex; a++) { AtomInfoType *ai = atomInfo + *(i2a++); if (GET_BIT(ai->visRep, cRepSphere)) { int c = ai->color; (*repActive) = true; if (c != last_color) { last_color = c; glColor3fv(ColorGet(G, c)); } switch (sphere_mode) { case 1: case 6: glVertex3fv(v); break; case 2: case 3: case 7: case 8: { float cur_radius = ai->vdw * pixel_scale; if (last_radius != cur_radius) { glEnd(); if (clamp_size_flag) if (cur_radius > max_radius) cur_radius = max_radius; glPointSize(cur_radius); glBegin(GL_POINTS); last_radius = cur_radius; } glVertex3fv(v); } break; } } v += 3; } glEnd(); glEnable(GL_LIGHTING); if (sphere_mode == 3) { glDisable(GL_POINT_SMOOTH); glAlphaFunc(GL_GREATER, 0.05F); } else { glEnable(GL_ALPHA_TEST); } } void RenderImmediate_DoPreGL(PyMOLGlobals *G, int sphere_mode, float *pixel_scale, CoordSet *cs, ObjectMolecule *obj, float sphere_scale) { switch (sphere_mode) { case 2: case 7: glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); glDisable(GL_POINT_SMOOTH); glDisable(GL_ALPHA_TEST); (*pixel_scale) *= 1.4F; glPointSize(1.0F); break; case 3: case 8: glEnable(GL_POINT_SMOOTH); glAlphaFunc(GL_GREATER, 0.5F); glEnable(GL_ALPHA_TEST); glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); glPointSize(1.0F); (*pixel_scale) *= 2.0F; break; case 4: glEnable(GL_POINT_SMOOTH); glEnable(GL_ALPHA_TEST); glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); glPointSize(1.0F); (*pixel_scale) *= 2.0F; break; default: glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); glDisable(GL_POINT_SMOOTH); glDisable(GL_ALPHA_TEST); glPointSize(SettingGet_f(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_point_size)); break; } } #endif void RepSphereRenderImmediate(CoordSet *cs, RenderInfo *info) { #ifndef PURE_OPENGL_ES_2 PyMOLGlobals *G = cs->State.G; if (info->ray || info->pick || (!(G->HaveGUI && G->ValidContext))) return; else { int repActive = false; ObjectMolecule *obj = cs->Obj; int sphere_mode = SettingGet_i(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_mode); float sphere_scale = SettingGet_f(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_scale); if (sphere_mode > 0) { /* point-based modees */ float pixel_scale = 1.0F / info->vertex_scale; RenderImmediate_DoPreGL(G, sphere_mode, &pixel_scale, cs, obj, sphere_scale); switch (sphere_mode) { #ifdef _PYMOL_ARB_SHADERS case 5: RenderSphereMode_Immediate_5(G, info, cs, obj, &repActive, sphere_scale); break; #endif case 4: // sphere_mode 4 taken out: many points per sphere to make them look // good, one specular light break; default: RenderSphereMode_Immediate_1_2_3(G, info, cs, obj, &repActive, pixel_scale, sphere_mode); } } else { RenderSphereMode_Immediate_Triangles(G, cs, obj, &repActive, sphere_scale); } if (!repActive) /* didn't draw a single sphere, so we can skip this representation next time around */ cs->Active[cRepSphere] = false; } #endif }