mirror of
https://github.com/schrodinger/pymol-open-source.git
synced 2026-06-03 19:54:24 +08:00
346 lines
10 KiB
C++
346 lines
10 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"Base.h"
|
|
#include"Err.h"
|
|
#include"RepEllipsoid.h"
|
|
#include"Color.h"
|
|
#include"Setting.h"
|
|
#include"Feedback.h"
|
|
#include"Matrix.h"
|
|
#include"CGO.h"
|
|
#include "CoordSet.h"
|
|
|
|
struct RepEllipsoid : Rep {
|
|
using Rep::Rep;
|
|
|
|
~RepEllipsoid() override;
|
|
|
|
cRep_t type() const override { return cRepEllipsoid; }
|
|
void render(RenderInfo* info) override;
|
|
|
|
CGO* ray = nullptr;
|
|
CGO* std = nullptr;
|
|
CGO* shaderCGO = nullptr;
|
|
};
|
|
|
|
#include"ObjectMolecule.h"
|
|
|
|
RepEllipsoid::~RepEllipsoid()
|
|
{
|
|
auto I = this;
|
|
CGOFree(I->ray);
|
|
CGOFree(I->std);
|
|
CGOFree(I->shaderCGO);
|
|
}
|
|
|
|
void RepEllipsoid::render(RenderInfo* info)
|
|
{
|
|
auto I = this;
|
|
CRay *ray = info->ray;
|
|
auto pick = info->pick;
|
|
int ok = true;
|
|
|
|
PyMOLGlobals *G = I->G;
|
|
if(ray) {
|
|
int try_std = false;
|
|
PRINTFD(G, FB_RepEllipsoid)
|
|
" RepEllipsoidRender: rendering ray...\n" ENDFD;
|
|
|
|
if(I->ray){
|
|
int rayok = CGORenderRay(I->ray, ray, info, nullptr, nullptr, I->cs->Setting.get(), I->obj->Setting.get());
|
|
if (!rayok){
|
|
CGOFree(I->ray);
|
|
try_std = true;
|
|
}
|
|
} else {
|
|
try_std = true;
|
|
}
|
|
if(try_std && I->std){
|
|
ok &= CGORenderRay(I->std, ray, info, nullptr, nullptr, I->cs->Setting.get(), I->obj->Setting.get());
|
|
if (!ok){
|
|
CGOFree(I->std);
|
|
}
|
|
}
|
|
CHECKOK(ok, I->std);
|
|
} else if(G->HaveGUI && G->ValidContext) {
|
|
|
|
if(pick) {
|
|
if(I->shaderCGO) {
|
|
CGORenderPicking(I->shaderCGO, info, &I->context,
|
|
I->cs->Setting.get(), I->obj->Setting.get());
|
|
} else if(I->std) {
|
|
CGORenderPicking(I->std, info, &I->context,
|
|
I->cs->Setting.get(), I->obj->Setting.get());
|
|
}
|
|
} else {
|
|
int use_shaders;
|
|
use_shaders = SettingGetGlobal_b(G, cSetting_use_shaders);
|
|
|
|
PRINTFD(G, FB_RepEllipsoid)
|
|
" RepEllipsoidRender: rendering GL...\n" ENDFD;
|
|
|
|
if (use_shaders){
|
|
if (!I->shaderCGO){
|
|
I->shaderCGO = CGOOptimizeToVBONotIndexed(I->std, 0);
|
|
assert(I->shaderCGO->use_shader);
|
|
}
|
|
} else {
|
|
CGOFree(I->shaderCGO);
|
|
}
|
|
if (I->shaderCGO){
|
|
CGORender(I->shaderCGO, nullptr, I->cs->Setting.get(), I->obj->Setting.get(), info, I);
|
|
} else if(I->std){
|
|
CGORender(I->std, nullptr, I->cs->Setting.get(), I->obj->Setting.get(), info, I);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const double problevel[50] = { 0.4299, 0.5479, 0.6334, 0.7035, 0.7644,
|
|
0.8192, 0.8694, 0.9162, 0.9605, 1.0026,
|
|
1.0430, 1.0821, 1.1200, 1.1570, 1.1932,
|
|
1.2288, 1.2638, 1.2985, 1.3330, 1.3672,
|
|
1.4013, 1.4354, 1.4695, 1.5037, 1.5382,
|
|
1.5729, 1.6080, 1.6436, 1.6797, 1.7164,
|
|
1.7540, 1.7924, 1.8318, 1.8724, 1.9144,
|
|
1.9580, 2.0034, 2.0510, 2.1012, 2.1544,
|
|
2.2114, 2.2730, 2.3404, 2.4153, 2.5003,
|
|
2.5997, 2.7216, 2.8829, 3.1365, 6.0000
|
|
};
|
|
|
|
/**
|
|
* Return true if backbone atom that should be hidden with side_chain_helper
|
|
*/
|
|
static bool is_sidechainhelper_hidden(PyMOLGlobals * G, const AtomInfoType * ai) {
|
|
if (!(ai->flags & cAtomFlag_polymer))
|
|
return false;
|
|
|
|
switch (ai->protons) {
|
|
case cAN_C:
|
|
return ai->name == G->lex_const.C;
|
|
case cAN_N:
|
|
return ai->name == G->lex_const.N && ai->resn != G->lex_const.PRO;
|
|
case cAN_O:
|
|
return ai->name == G->lex_const.O;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
Rep *RepEllipsoidNew(CoordSet * cs, int state)
|
|
{
|
|
PyMOLGlobals *G = cs->G;
|
|
ObjectMolecule *obj;
|
|
int ok = true;
|
|
|
|
// skip if no dots are visible
|
|
if(!cs->hasRep(cRepEllipsoidBit))
|
|
return nullptr;
|
|
|
|
auto I = new RepEllipsoid(cs, state);
|
|
CHECKOK(ok, I);
|
|
if (!ok)
|
|
return nullptr;
|
|
|
|
obj = cs->Obj;
|
|
|
|
{
|
|
int ellipsoid_color = SettingGet_color(G, cs->Setting.get(), obj->Setting.get(),
|
|
cSetting_ellipsoid_color);
|
|
|
|
int cartoon_side_chain_helper = SettingGet_b(G, cs->Setting.get(), obj->Setting.get(),
|
|
cSetting_cartoon_side_chain_helper);
|
|
|
|
int ribbon_side_chain_helper = SettingGet_b(G, cs->Setting.get(), obj->Setting.get(),
|
|
cSetting_ribbon_side_chain_helper);
|
|
|
|
float ellipsoid_scale = SettingGet_f(G, cs->Setting.get(), obj->Setting.get(),
|
|
cSetting_ellipsoid_scale);
|
|
|
|
float transp = SettingGet_f(G, cs->Setting.get(), obj->Setting.get(),
|
|
cSetting_ellipsoid_transparency);
|
|
|
|
int pickable = SettingGet_b(G, cs->Setting.get(), obj->Setting.get(),
|
|
cSetting_pickable);
|
|
|
|
float prob = SettingGet_f(G, cs->Setting.get(), obj->Setting.get(),
|
|
cSetting_ellipsoid_probability);
|
|
double matrix_factor = 0.0F;
|
|
float pradius = 0.0F;
|
|
{
|
|
|
|
int iprob = (prob + 0.01F) * 50.0F - 1;
|
|
if(iprob < 0)
|
|
iprob = 0;
|
|
if(iprob > 49)
|
|
iprob = 49;
|
|
pradius = problevel[iprob];
|
|
matrix_factor = -(1 / (pradius * pradius));
|
|
}
|
|
|
|
I->ray = CGONew(G); /* describe the ellipsoids analytically */
|
|
CHECKOK(ok, I->ray);
|
|
if(I->ray) {
|
|
int a, a1;
|
|
AtomInfoType *ai;
|
|
float last_alpha = 1.0F;
|
|
|
|
double *csmatrix = SettingGet_i(G, cs->Setting.get(), obj->Setting.get(),
|
|
cSetting_matrix_mode) > 0 ? nullptr : cs->Matrix.data();
|
|
|
|
for(a = 0; a < cs->NIndex; a++) {
|
|
a1 = cs->IdxToAtm[a];
|
|
ai = obj->AtomInfo + a1;
|
|
if (!ai->anisou || !(ai->visRep & cRepEllipsoidBit))
|
|
continue;
|
|
|
|
if (is_sidechainhelper_hidden(G, ai)) {
|
|
if ((ai->visRep & cRepCartoonBit) && AtomSettingGetWD(G, ai,
|
|
cSetting_cartoon_side_chain_helper, /* d= */ cartoon_side_chain_helper))
|
|
continue;
|
|
|
|
if ((ai->visRep & cRepRibbonBit) && AtomSettingGetWD(G, ai,
|
|
cSetting_ribbon_side_chain_helper, /* d= */ ribbon_side_chain_helper))
|
|
continue;
|
|
}
|
|
|
|
{
|
|
{
|
|
int n_rot;
|
|
double matrix[16];
|
|
double e_val[4];
|
|
double e_vec[16];
|
|
|
|
matrix[0] = ai->anisou[0]; // U11
|
|
matrix[1] = ai->anisou[3]; // U12
|
|
matrix[2] = ai->anisou[4]; // U13
|
|
matrix[3] = 0.0;
|
|
matrix[4] = ai->anisou[3]; // U12
|
|
matrix[5] = ai->anisou[1]; // U22
|
|
matrix[6] = ai->anisou[5]; // U23
|
|
matrix[7] = 0.0;
|
|
matrix[8] = ai->anisou[4]; // U13
|
|
matrix[9] = ai->anisou[5]; // U23
|
|
matrix[10] = ai->anisou[2]; // U33
|
|
matrix[11] = 0.0;
|
|
matrix[12] = 0.0;
|
|
matrix[13] = 0.0;
|
|
matrix[14] = 0.0;
|
|
matrix[15] = matrix_factor;
|
|
|
|
if(xx_matrix_jacobi_solve(e_vec, e_val, &n_rot, matrix, 4)) {
|
|
|
|
const float* v = cs->coordPtr(a);
|
|
|
|
float mag[3];
|
|
float scale[3];
|
|
|
|
float mx;
|
|
float r_el, n0[3], n1[3], n2[3];
|
|
|
|
float at_ellipsoid_scale = AtomSettingGetWD(G, ai, cSetting_ellipsoid_scale, ellipsoid_scale);
|
|
float at_transp = AtomSettingGetWD(G, ai, cSetting_ellipsoid_transparency, transp);
|
|
int c1 = AtomSettingGetWD(G, ai, cSetting_ellipsoid_color, ellipsoid_color);
|
|
|
|
if(c1 == -1)
|
|
c1 = ai->color;
|
|
|
|
if(csmatrix)
|
|
left_multiply44d44d(csmatrix, e_vec);
|
|
|
|
n0[0] = e_vec[0];
|
|
n0[1] = e_vec[4];
|
|
n0[2] = e_vec[8];
|
|
n1[0] = e_vec[1];
|
|
n1[1] = e_vec[5];
|
|
n1[2] = e_vec[9];
|
|
n2[0] = e_vec[2];
|
|
n2[1] = e_vec[6];
|
|
n2[2] = e_vec[10];
|
|
|
|
normalize3f(n0);
|
|
normalize3f(n1);
|
|
normalize3f(n2);
|
|
mag[0] = sqrt1f(e_val[0]);
|
|
mag[1] = sqrt1f(e_val[1]);
|
|
mag[2] = sqrt1f(e_val[2]);
|
|
|
|
mx = mag[0];
|
|
if(mx < mag[1])
|
|
mx = mag[1];
|
|
if(mx < mag[2])
|
|
mx = mag[2];
|
|
|
|
scale[0] = mag[0] / mx;
|
|
scale[1] = mag[1] / mx;
|
|
scale[2] = mag[2] / mx;
|
|
|
|
scale3f(n0, scale[0], n0);
|
|
scale3f(n1, scale[1], n1);
|
|
scale3f(n2, scale[2], n2);
|
|
|
|
r_el = mx * pradius * at_ellipsoid_scale;
|
|
|
|
{
|
|
float vc[3];
|
|
if(ColorCheckRamped(G, c1)) {
|
|
ColorGetRamped(G, c1, v, vc, state);
|
|
ok &= CGOColorv(I->ray, vc);
|
|
} else {
|
|
ok &= CGOColorv(I->ray, ColorGet(G, c1));
|
|
}
|
|
}
|
|
|
|
if (ok) {
|
|
float alpha = 1.0F - at_transp;
|
|
if(alpha != last_alpha) {
|
|
ok &= CGOAlpha(I->ray, alpha);
|
|
last_alpha = alpha;
|
|
|
|
if (at_transp > 0) {
|
|
I->setHasTransparency();
|
|
}
|
|
}
|
|
}
|
|
if(ok && pickable && (!ai->masked))
|
|
ok &= CGOPickColor(I->ray, a1, cPickableAtom);
|
|
|
|
if (ok)
|
|
ok &= CGOEllipsoid(I->ray, v, r_el, n0, n1, n2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (ok)
|
|
ok &= CGOStop(I->ray);
|
|
I->std = CGOSimplify(I->ray, 0); /* convert analytical to discrete */
|
|
CHECKOK(ok, I->std);
|
|
}
|
|
}
|
|
if (!ok){
|
|
delete I;
|
|
I = nullptr;
|
|
}
|
|
return (Rep *) I;
|
|
}
|