mirror of
https://github.com/schrodinger/pymol-open-source.git
synced 2026-06-04 20:04:21 +08:00
297 lines
8.9 KiB
C++
297 lines
8.9 KiB
C++
|
|
/*
|
|
A* -------------------------------------------------------------------
|
|
B* This file contains source code for the PyMOL computer program
|
|
C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
|
|
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"os_python.h"
|
|
|
|
#include"os_predef.h"
|
|
#include"os_std.h"
|
|
#include"os_gl.h"
|
|
|
|
#include"Err.h"
|
|
#include"RepNonbonded.h"
|
|
#include"Color.h"
|
|
#include"Scene.h"
|
|
#include"main.h"
|
|
#include"Setting.h"
|
|
#include"ShaderMgr.h"
|
|
#include"CGO.h"
|
|
#include"CoordSet.h"
|
|
|
|
struct RepNonbonded : Rep {
|
|
using Rep::Rep;
|
|
|
|
~RepNonbonded() override;
|
|
|
|
cRep_t type() const override { return cRepNonbonded; }
|
|
void render(RenderInfo* info) override;
|
|
|
|
CGO *primitiveCGO;
|
|
CGO *shaderCGO;
|
|
bool shaderCGO_has_cylinders;
|
|
};
|
|
|
|
#include"ObjectMolecule.h"
|
|
|
|
RepNonbonded::~RepNonbonded()
|
|
{
|
|
CGOFree(primitiveCGO);
|
|
CGOFree(shaderCGO);
|
|
}
|
|
|
|
void RepNonbondedRenderImmediate(CoordSet * cs, RenderInfo * info)
|
|
{
|
|
#ifndef PURE_OPENGL_ES_2
|
|
PyMOLGlobals *G = cs->G;
|
|
if(info->ray || info->pick || (!(G->HaveGUI && G->ValidContext)))
|
|
return;
|
|
else {
|
|
int active = false;
|
|
ObjectMolecule *obj = cs->Obj;
|
|
float line_width =
|
|
SettingGet_f(G, cs->Setting.get(), obj->Setting.get(), cSetting_line_width);
|
|
float nonbonded_size =
|
|
SettingGet_f(G, cs->Setting.get(), obj->Setting.get(), cSetting_nonbonded_size);
|
|
|
|
if(info->width_scale_flag)
|
|
glLineWidth(line_width * info->width_scale);
|
|
else
|
|
glLineWidth(line_width);
|
|
|
|
SceneResetNormal(G, true);
|
|
|
|
if(!info->line_lighting)
|
|
glDisable(GL_LIGHTING);
|
|
glBegin(GL_LINES);
|
|
{
|
|
int a;
|
|
int nIndex = cs->NIndex;
|
|
const AtomInfoType* atomInfo = obj->AtomInfo.data();
|
|
const int* i2a = cs->IdxToAtm.data();
|
|
int last_color = -1;
|
|
const float *v = cs->Coord;
|
|
|
|
for(a = 0; a < nIndex; a++) {
|
|
const AtomInfoType* ai = atomInfo + *(i2a++);
|
|
if((!ai->bonded) && (ai->visRep & cRepNonbondedBit)) {
|
|
int c = ai->color;
|
|
float v0 = v[0];
|
|
float v1 = v[1];
|
|
float v2 = v[2];
|
|
active = true;
|
|
if(c != last_color) {
|
|
last_color = c;
|
|
glColor3fv(ColorGet(G, c));
|
|
}
|
|
|
|
glVertex3f(v0 - nonbonded_size, v1, v2);
|
|
glVertex3f(v0 + nonbonded_size, v1, v2);
|
|
|
|
glVertex3f(v0, v1 - nonbonded_size, v2);
|
|
glVertex3f(v0, v1 + nonbonded_size, v2);
|
|
|
|
glVertex3f(v0, v1, v2 - nonbonded_size);
|
|
glVertex3f(v0, v1, v2 + nonbonded_size);
|
|
}
|
|
v += 3;
|
|
}
|
|
}
|
|
glEnd();
|
|
glEnable(GL_LIGHTING);
|
|
if(!active)
|
|
cs->Active[cRepNonbonded] = false;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static int RepNonbondedCGOGenerate(RepNonbonded * I, RenderInfo * info)
|
|
{
|
|
PyMOLGlobals *G = I->G;
|
|
float alpha;
|
|
int ok = true;
|
|
CGO *convertcgo = nullptr;
|
|
short nonbonded_as_cylinders ;
|
|
short use_shader;
|
|
float nonbonded_size =
|
|
SettingGet_f(G, I->cs->Setting.get(), I->obj->Setting.get(), cSetting_nonbonded_size);
|
|
|
|
nonbonded_as_cylinders = SettingGetGlobal_b(G, cSetting_render_as_cylinders) && SettingGetGlobal_b(G, cSetting_nonbonded_as_cylinders);
|
|
use_shader = SettingGetGlobal_b(G, cSetting_nonbonded_use_shader) &
|
|
SettingGetGlobal_b(G, cSetting_use_shaders);
|
|
|
|
alpha =
|
|
SettingGet_f(G, I->cs->Setting.get(), I->obj->Setting.get(), cSetting_nonbonded_transparency);
|
|
alpha = 1.0F - alpha;
|
|
if(fabs(alpha - 1.0) < R_SMALL4)
|
|
alpha = 1.0F;
|
|
|
|
if (use_shader){
|
|
if (ok && I->shaderCGO){
|
|
CGOFree(I->shaderCGO);
|
|
}
|
|
if (ok){
|
|
if (nonbonded_as_cylinders){
|
|
CGO *tmpCGO = CGONew(G);
|
|
if (ok) ok &= CGOEnable(tmpCGO, GL_CYLINDER_SHADER);
|
|
if (ok) ok &= CGOSpecial(tmpCGO, CYLINDER_WIDTH_FOR_REPWIRE);
|
|
convertcgo = CGOConvertCrossesToCylinderShader(I->primitiveCGO, tmpCGO, nonbonded_size);
|
|
if (ok) ok &= CGOAppendNoStop(tmpCGO, convertcgo);
|
|
if (ok) ok &= CGODisable(tmpCGO, GL_CYLINDER_SHADER);
|
|
if (ok) ok &= CGOStop(tmpCGO);
|
|
CGOFreeWithoutVBOs(convertcgo);
|
|
I->shaderCGO_has_cylinders = true;
|
|
convertcgo = tmpCGO;
|
|
} else {
|
|
bool trilines = SettingGetGlobal_b(G, cSetting_trilines);
|
|
CGO *tmpCGO = CGONew(G), *tmp2CGO;
|
|
int shader = trilines ? GL_TRILINES_SHADER : GL_LINE_SHADER;
|
|
|
|
if (ok) ok &= CGOEnable(tmpCGO, shader);
|
|
if (ok) ok &= CGODisable(tmpCGO, CGO_GL_LIGHTING);
|
|
if (trilines) {
|
|
if (ok) ok &= CGOSpecial(tmpCGO, LINEWIDTH_DYNAMIC_WITH_SCALE);
|
|
tmp2CGO = CGOConvertCrossesToTrilinesShader(I->primitiveCGO, tmpCGO, nonbonded_size);
|
|
} else {
|
|
tmp2CGO = CGOConvertCrossesToLinesShader(I->primitiveCGO, tmpCGO, nonbonded_size);
|
|
}
|
|
if (ok) ok &= CGOAppendNoStop(tmpCGO, tmp2CGO);
|
|
if (ok) ok &= CGODisable(tmpCGO, shader);
|
|
if (ok) ok &= CGOStop(tmpCGO);
|
|
CGOFreeWithoutVBOs(tmp2CGO);
|
|
convertcgo = tmpCGO;
|
|
I->shaderCGO_has_cylinders = false;
|
|
}
|
|
convertcgo->use_shader = true;
|
|
}
|
|
CHECKOK(ok, convertcgo);
|
|
if (!ok || convertcgo){
|
|
CGOFree(I->shaderCGO);
|
|
I->shaderCGO = convertcgo;
|
|
I->shaderCGO->use_shader = use_shader;
|
|
convertcgo = nullptr;
|
|
}
|
|
} else {
|
|
// no shaders
|
|
convertcgo = CGOCombineBeginEnd(I->shaderCGO, 0);
|
|
CGOFree(I->shaderCGO);
|
|
I->shaderCGO = convertcgo;
|
|
I->shaderCGO->use_shader = use_shader;
|
|
convertcgo = nullptr;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
void RepNonbonded::render(RenderInfo* info)
|
|
{
|
|
auto I = this;
|
|
CRay *ray = info->ray;
|
|
auto pick = info->pick;
|
|
int ok = true;
|
|
float alpha =
|
|
SettingGet_f(G, I->cs->Setting.get(), I->obj->Setting.get(), cSetting_nonbonded_transparency);
|
|
alpha = 1.0F - alpha;
|
|
if(fabs(alpha - 1.0) < R_SMALL4)
|
|
alpha = 1.0F;
|
|
if(ray) {
|
|
#ifndef _PYMOL_NO_RAY
|
|
CGORenderRay(I->primitiveCGO, ray, info, nullptr, nullptr, I->cs->Setting.get(), I->cs->Obj->Setting.get());
|
|
ray->transparentf(0.0);
|
|
#endif
|
|
} else if(G->HaveGUI && G->ValidContext) {
|
|
if(pick) {
|
|
CGORenderPicking(I->shaderCGO ? I->shaderCGO : I->primitiveCGO, info, &I->context, I->cs->Setting.get(), I->obj->Setting.get());
|
|
} else {
|
|
/* not pick, but render */
|
|
bool use_shader = SettingGetGlobal_b(G, cSetting_nonbonded_use_shader) && SettingGetGlobal_b(G, cSetting_use_shaders);
|
|
if (!use_shader){
|
|
CGORender(I->primitiveCGO, nullptr, nullptr, nullptr, info, I);
|
|
return;
|
|
}
|
|
bool nonbonded_as_cylinders = SettingGetGlobal_b(G, cSetting_render_as_cylinders) && SettingGetGlobal_b(G, cSetting_nonbonded_as_cylinders);
|
|
if (I->shaderCGO && use_shader != I->shaderCGO->use_shader){
|
|
CGOFree(I->shaderCGO);
|
|
I->shaderCGO = 0;
|
|
}
|
|
|
|
if (I->shaderCGO && (nonbonded_as_cylinders ^ I->shaderCGO_has_cylinders)){
|
|
CGOFree(I->shaderCGO);
|
|
I->shaderCGO = 0;
|
|
}
|
|
|
|
if (!I->shaderCGO){
|
|
I->shaderCGO = CGONew(G);
|
|
CHECKOK(ok, I->shaderCGO);
|
|
if (ok){
|
|
I->shaderCGO->use_shader = use_shader;
|
|
}
|
|
ok &= RepNonbondedCGOGenerate(I, info);
|
|
}
|
|
CGORender(I->shaderCGO, nullptr, nullptr, nullptr, info, I);
|
|
}
|
|
}
|
|
}
|
|
|
|
Rep *RepNonbondedNew(CoordSet * cs, int state)
|
|
{
|
|
PyMOLGlobals *G = cs->G;
|
|
bool hasNonbondedAtoms = false;
|
|
|
|
ObjectMolecule *obj = cs->Obj;
|
|
|
|
if((obj->RepVisCache & cRepNonbondedBit)){
|
|
for(int a = 0; a < cs->NIndex; a++) {
|
|
AtomInfoType *ai = obj->AtomInfo + cs->IdxToAtm[a];
|
|
if (!ai->bonded && (ai->visRep & cRepNonbondedBit)){
|
|
hasNonbondedAtoms = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(!hasNonbondedAtoms) {
|
|
return (nullptr); /* skip if no dots are visible */
|
|
}
|
|
|
|
auto I = new RepNonbonded(cs, state);
|
|
|
|
I->shaderCGO = nullptr;
|
|
|
|
I->primitiveCGO = CGONew(G);
|
|
|
|
CGOSpecialWithArg(I->primitiveCGO, LINE_LIGHTING, 0.f);
|
|
CGOSpecial(I->primitiveCGO, LINEWIDTH_FOR_LINES);
|
|
CGOBegin(I->primitiveCGO, GL_LINES); // for immediate mode
|
|
bool first = true;
|
|
int a1, c1;
|
|
float tmpColor[3];
|
|
for(int a = 0; a < cs->NIndex; a++){
|
|
a1 = cs->IdxToAtm[a];
|
|
AtomInfoType *ai = obj->AtomInfo + a1;
|
|
if(!ai->bonded && (ai->visRep & cRepNonbondedBit)) {
|
|
c1 = ai->color;
|
|
const float* v1 = cs->coordPtr(a);
|
|
ColorGetCheckRamped(G, c1, v1, tmpColor, state);
|
|
if (first || !equal3f(I->primitiveCGO->color, tmpColor)){
|
|
CGOColorv(I->primitiveCGO, tmpColor);
|
|
}
|
|
CGOPickColor(I->primitiveCGO, a1, (ai->masked) ? cPickableNoPick : cPickableAtom);
|
|
CGOVertexCrossv(I->primitiveCGO, v1);
|
|
first = false;
|
|
}
|
|
}
|
|
CGOEnd(I->primitiveCGO); // for immediate mode
|
|
CGOSpecialWithArg(I->primitiveCGO, LINE_LIGHTING, 1.f);
|
|
return (Rep *) I;
|
|
}
|