/* 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; }