"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "layer2/RepSphere.cpp" between
pymol-v2.1.0.tar.bz2 and pymol-open-source-2.2.0.tar.gz

About: PyMOL is a Python-enhanced molecular graphics tool. It excels at 3D visualization of proteins, small molecules, density, surfaces, and trajectories. It also includes molecular editing, ray tracing, and movies. Open Source version.

RepSphere.cpp  (pymol-v2.1.0.tar.bz2):RepSphere.cpp  (pymol-open-source-2.2.0)
skipping to change at line 25 skipping to change at line 25
Z* ------------------------------------------------------------------- Z* -------------------------------------------------------------------
*/ */
#include"os_python.h" #include"os_python.h"
#include"os_predef.h" #include"os_predef.h"
#include"os_std.h" #include"os_std.h"
#include"os_gl.h" #include"os_gl.h"
#include"Base.h" #include"Base.h"
#include"OOMac.h" #include"OOMac.h"
#include"RepSphere.h" #include"RepSphere.h"
#include"RepSphereImmediate.h"
#include"RepSphereGenerate.h"
#include"Color.h" #include"Color.h"
#include"Sphere.h" #include"Sphere.h"
#include"Map.h" #include"Map.h"
#include"Setting.h" #include"Setting.h"
#include"main.h" #include"main.h"
#include"Util.h" #include"Util.h"
#include"Feedback.h" #include"Feedback.h"
#include "ShaderMgr.h" #include "ShaderMgr.h"
#include "Scene.h" #include "Scene.h"
#include"CGO.h" #include"CGO.h"
#include"ObjectMolecule.h" #include"ObjectMolecule.h"
#include "Lex.h" #include "Lex.h"
#include "ShaderText.h" #define SPHERE_NORMAL_RANGE 6.f
#define SPHERE_NORMAL_RANGE2 (SPHERE_NORMAL_RANGE*SPHERE_NORMAL_RANGE)
#ifdef NT
#undef NT
#endif
/* defer_builds_mode = 5 : Immediate mode for any sphere_mode /* defer_builds_mode = 5 : Immediate mode for any sphere_mode
sphere_mode : sphere_mode :
0) Geometry shaders (quality based on sphere_quality, default 1) 0) Geometry shaders (quality based on sphere_quality, default 1)
1) rectangular points with the same size, that can be changed with sphere_poi nt_size 1) rectangular points with the same size, that can be changed with sphere_poi nt_size
2) rectangles with constant size relative to vdw and scene scale (i.e., chang es when zoomed) 2) rectangles with constant size relative to vdw and scene scale (i.e., chang es when zoomed)
maxed by a multiple of sphere_point_max_size (set it below 1 to see it inf luence, 3*pixel_scale max) maxed by a multiple of sphere_point_max_size (set it below 1 to see it inf luence, 3*pixel_scale max)
3) same as 2 but with circles 3) same as 2 but with circles
4) Draw multiple points for each sphere to mimic specular reflection of one l ight on the sphere 4) no longer available
5) Uses the fast ARB Shader that approximates spheres as circles 5) Uses the fast ARB Shader that approximates spheres as circles
6-8) same as 1-3 but with normals computed from close atoms to mimic nice lig hting
9) GLSL Shader Spheres (only when shaders are available) 9) GLSL Shader Spheres (only when shaders are available)
*/ */
typedef struct RepSphere {
Rep R;
float *V; /* triangle vertices (if any) */
float *VC; /* 8 floats per sphere: 3 color, 1 transparency, 3 coordinates, 1
radius */
float *VN; /* normals (if any) computed in RepSphereComputeSphereNormals() *
/
SphereRec *SP;
SphereRec *SSP; /* sphere record used for picking (if set, otherwise 0) and d
irect mode */
int *NT;
int N, NC, NP; /* N - number of vertices in V triangles,
NC - number of spheres stored in VC,
NP - number of pickable atoms */
int cullFlag;
int spheroidFlag;
int *LastVisib;
int *LastColor;
float LastVertexScale;
int VariableAlphaFlag;
CGO *shaderCGO;
} RepSphere;
void RepSphereFree(RepSphere * I); void RepSphereFree(RepSphere * I);
int RepSphereSameVis(RepSphere * I, CoordSet * cs); int RepSphereSameVis(RepSphere * I, CoordSet * cs);
void RepSphereFree(RepSphere * I) void RepSphereFree(RepSphere * I)
{ {
if (I->shaderCGO ){ if (I->primitiveCGO == I->renderCGO) {
CGOFree(I->shaderCGO); I->primitiveCGO = 0;
I->shaderCGO = 0;
} }
CGOFree(I->primitiveCGO);
FreeP(I->VC); CGOFree(I->renderCGO);
FreeP(I->V); CGOFree(I->spheroidCGO);
FreeP(I->VN);
FreeP(I->NT);
FreeP(I->LastColor); FreeP(I->LastColor);
FreeP(I->LastVisib); FreeP(I->LastVisib);
RepPurge(&I->R); RepPurge(&I->R);
OOFreeP(I); OOFreeP(I);
} }
/* MULTI-INSTSANCE TODO: isn't this a conflict? */ /* MULTI-INSTSANCE TODO: isn't this a conflict? */
static CShaderPrg *sphereARBShaderPrg = NULL; CShaderPrg *sphereARBShaderPrg = NULL;
#ifdef _PYMOL_ARB_SHADERS
static void RepSphereRenderOneSphere_ARB(PyMOLGlobals *G, RenderInfo *info,
float *color, float *last_radius, float *cur_radius, float *fog_info,
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);
}
#endif
static void RenderSpherePopulateVariables(PyMOLGlobals *G, RenderInfo *info, void RenderSphereComputeFog(PyMOLGlobals *G, RenderInfo *info, float *fog_info)
float *nv, float *fog_info, float *z_front, float *z_back)
{ {
/* compute -Ze = (Wc) of fog start */ /* compute -Ze = (Wc) of fog start */
float nv[4];
nv[3] = nv[3] =
(info->front + (info->front +
(info->back - info->front) * SettingGetGlobal_f(G, cSetting_fog_start)); (info->back - info->front) * SettingGetGlobal_f(G, cSetting_fog_start));
/* compute Zc of fog start using std. perspective transformation */ /* compute Zc of fog start using std. perspective transformation */
nv[2] = nv[2] =
(nv[3] * (info->back + info->front) - (nv[3] * (info->back + info->front) -
2 * (info->back * info->front)) / (info->back - info->front); 2 * (info->back * info->front)) / (info->back - info->front);
/* compute Zc/Wc to get normalized depth coordinate of fog start */ /* compute Zc/Wc to get normalized depth coordinate of fog start */
nv[0] = (nv[2] / nv[3]); nv[0] = (nv[2] / nv[3]);
fog_info[0] = (nv[0] * 0.5) + 0.5; fog_info[0] = (nv[0] * 0.5) + 0.5;
fog_info[1] = 1.0F / (1.0 - fog_info[0]); /* effective range of fog */ fog_info[1] = 1.0F / (1.0 - fog_info[0]); /* effective range of fog */
(*z_front) = info->stereo_front;
(*z_back) = info->back + ((info->back + info->front) * 0.25);
}
#ifdef _PYMOL_ARB_SHADERS
void RenderSphereMode_Immediate_5(PyMOLGlobals *G, RenderInfo *info, CoordSet *c
s, ObjectMolecule *obj, int *repActive, float sphere_scale){
if (!sphereARBShaderPrg){
sphereARBShaderPrg = CShaderPrg_NewARB(G, "sphere_arb", sphere_arb_vs, spher
e_arb_fs);
}
if(sphereARBShaderPrg){
float fog_info[3];
float nv[4];
float z_front, z_back;
RenderSpherePopulateVariables(G, info, nv, fog_info, &z_front, &z_back);
CShaderPrg_Enable_SphereShaderARB(G);
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_rad
ius, &cur_radius, fog_info, vr);
}
v += 3;
}
glEnd();
}
CShaderPrg_DisableARB(sphereARBShaderPrg);
}
}
#endif
static void RenderSphereMode_Immediate_4(PyMOLGlobals *G, RenderInfo *info,
CoordSet *cs, ObjectMolecule *obj, int *repActive, float pixel_scale)
{
#ifndef PURE_OPENGL_ES_2
int repeat = true;
const float _1 = 1.0F;
const float _2 = 2.0F;
float x_add = 0.0F, y_add = 0.0F, z_add = 0.0F;
float z_factor = 0.0F, r_factor = 1.0F;
float s_factor = 0.0F;
int pass = 0;
float max_size = SettingGet_f(G, cs->Setting, obj->Obj.Setting,
cSetting_sphere_point_max_size);
int clamp_size_flag = (max_size >= 0.0F);
while(repeat) {
int a;
int nIndex = cs->NIndex;
AtomInfoType *atomInfo = obj->AtomInfo;
int *i2a = cs->IdxToAtm;
float *v = cs->Coord;
float last_radius = -1.0F;
float last_size = -1.0;
float largest = 0.0F;
float zz_factor = _1 - (float) pow(_1 - z_factor, 2);
if(zz_factor < 0.45F)
zz_factor = 0.45F;
repeat = false;
glBegin(GL_POINTS);
for(a = 0; a < nIndex; a++) {
AtomInfoType *ai = atomInfo + *(i2a++);
if(GET_BIT(ai->visRep,cRepSphere)) {
float cur_radius = ai->vdw;
(*repActive) = true;
if(last_radius != cur_radius) {
float clamp_radius = cur_radius;
float size = cur_radius * pixel_scale;
if(clamp_size_flag)
if(size > max_size) {
size = max_size;
clamp_radius = size / pixel_scale;
}
size *= r_factor;
if(size != last_size) {
glEnd();
if(size > largest)
largest = size;
if(size < _2) {
if(!pass) {
zz_factor = 1.0F;
s_factor = 0.0F;
}
}
if(size < _1) {
size = _1;
glDisable(GL_POINT_SMOOTH);
glDisable(GL_ALPHA_TEST);
} else {
glEnable(GL_POINT_SMOOTH);
glEnable(GL_ALPHA_TEST);
}
glPointSize(size);
glBegin(GL_POINTS);
}
x_add = z_factor * clamp_radius * info->view_normal[0];
y_add = z_factor * clamp_radius * info->view_normal[1];
z_add = z_factor * clamp_radius * info->view_normal[2];
last_radius = cur_radius;
last_size = size;
}
{
float *vc = ColorGet(G, ai->color);
float r = zz_factor * vc[0] + s_factor;
float g = zz_factor * vc[1] + s_factor;
float b = zz_factor * vc[2] + s_factor;
glColor3f(r > _1 ? _1 : r, g > _1 ? _1 : g, b > _1 ? _1 : b);
glVertex3f(v[0] + x_add, v[1] + y_add, v[2] + z_add);
}
}
v += 3;
}
glEnd();
if(largest > 2.0F) {
float reduce = (largest - 2.0F) / largest;
r_factor *= reduce;
z_factor = (float) sqrt1f(1.0F - (r_factor * r_factor));
s_factor = (float) pow(z_factor, 20.0F) * 0.5F;
repeat = true;
pass++;
}
}
glDisable(GL_POINT_SMOOTH);
printf("pass=%d\n", pass);
#endif
}
static void RenderSphereMode_Immediate_Triangles(PyMOLGlobals *G, CoordSet *cs,
ObjectMolecule *obj, int *repActive, float sphere_scale)
{
/* triangle-based spheres */
SphereRec *sp = G->Sphere->Sphere[0];
int ds = SettingGet_i(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_qualit
y);
if(ds < 0) {
sp = NULL;
} else {
if(ds > 4)
ds = 4;
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++);
#ifdef PURE_OPENGL_ES_2
/* TODO */
#else
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();
#endif
}
}
}
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_sca
le;
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_scal
e, 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;
}
}
void RepSphereRenderImmediate(CoordSet * cs, RenderInfo * info)
{
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_scal
e);
switch (sphere_mode){
#ifdef _PYMOL_ARB_SHADERS
case 5:
RenderSphereMode_Immediate_5(G, info, cs, obj, &repActive, sphere_scale);
break;
#endif
case 4:
RenderSphereMode_Immediate_4(G, info, cs, obj, &repActive, pixel_scale);
break;
default:
RenderSphereMode_Immediate_1_2_3(G, info, cs, obj, &repActive, pixel_scal
e, sphere_mode);
}
} else {
RenderSphereMode_Immediate_Triangles(G, cs, obj, &repActive, sphere_scale)
;
}
if(!repActive) /* didn't draw a single sphere, so we can skip t
his representation next time around */
cs->Active[cRepSphere] = false;
}
}
#ifdef PURE_OPENGL_ES_2
void RepSphereRenderPointsES(int nvertsarg, float *varg, float *vnarg);
void RepSphereRenderMode5PointsES(int nvertsarg, float *varg, float zz_factor, f
loat s_factor, float *dim_add, float _1);
void RepSphereRenderPointsDefaultES(RepSphere * I, Picking **pick, int nvertsarg
, int iarg, Pickable *parg, float *varg);
void RepSphereRenderPointsES(int nvertsarg, float *varg, float *vnarg){
/* TODO */
}
void RepSphereRenderMode5PointsES(int nvertsarg, float *varg, float zz_factor, f
loat s_factor, float *dim_add, float _1){
}
void RepSphereRenderPointsDefaultES(RepSphere * I, Picking **pick, int nvertsarg
, int iarg, Pickable *parg, float *varg){
}
#endif
static int RenderSphereMode_Direct(PyMOLGlobals *G, RepSphere *I,
RenderInfo * info, int carg, float **vptr, float alpha,
SphereRec *sphereRecPtr)
{
short use_shader, generate_shader_cgo = 0;
float *v = *vptr;
int c = carg;
int ok = true;
use_shader = SettingGetGlobal_b(G, cSetting_sphere_use_shader) &
SettingGetGlobal_b(G, cSetting_use_shaders);
if (I->shaderCGO && !use_shader){
CGOFree(I->shaderCGO);
I->shaderCGO = 0;
}
if (use_shader){
if (!I->shaderCGO){
I->shaderCGO = CGONew(G);
CHECKOK(ok, I->shaderCGO);
if (ok)
I->shaderCGO->use_shader = true;
generate_shader_cgo = 1;
} else {
I->shaderCGO->enable_shaders = true;
CGORenderGL(I->shaderCGO, NULL, NULL, NULL, info, &I->R);
return true;
}
}
if (generate_shader_cgo){
if(ok && sphereRecPtr) {
float last_vdw = -1.0F;
int variable_alpha = I->VariableAlphaFlag;
SphereRec *sp = sphereRecPtr;
while(ok && c--) {
Vector3f *sp_dot = sp->dot;
int b, *q, *s;
if(variable_alpha){
ok &= CGOAlpha(I->shaderCGO, v[3]);
} else {
ok &= CGOAlpha(I->shaderCGO, alpha);
}
if (ok)
ok &= CGOColorv(I->shaderCGO, v);
(*vptr)+=4; v = *vptr;
if (ok){
float vdw = v[3];
last_vdw = vdw;
q = sp->Sequence;
s = sp->StripLen;
for(b = 0; ok && b < sp->NStrip; b++) {
int d;
ok &= CGOBegin(I->shaderCGO, GL_TRIANGLE_STRIP);
for(d = 0; ok && d < (*s); d++) {
float *norm = sp_dot[*(q++)];
ok &= CGONormalv(I->shaderCGO, norm);
if (ok)
ok &= CGOVertex(I->shaderCGO, v[0] + vdw * norm[0], v[1] + vdw *
norm[1], v[2] + vdw * norm[2]);
}
if (ok)
ok &= CGOEnd(I->shaderCGO);
s++;
}
}
(*vptr)+=4; v = *vptr;
}
if (ok)
ok &= CGOStop(I->shaderCGO);
}
if (ok) {
CGO *convertcgo = CGOCombineBeginEnd(I->shaderCGO, 0), *convertcgo2;
CHECKOK(ok, convertcgo);
if (ok){
CGOFree(I->shaderCGO);
I->shaderCGO = convertcgo;
convertcgo2 = CGOOptimizeToVBONotIndexed(I->shaderCGO, 0);
CHECKOK(ok, convertcgo2);
if (ok){
CGOFree(I->shaderCGO);
I->shaderCGO = convertcgo2;
}
}
}
if (ok){
I->shaderCGO->enable_shaders = true;
CGORenderGL(I->shaderCGO, NULL, NULL, NULL, info, &I->R);
}
} else {
if(sphereRecPtr) {
float last_vdw = -1.0F;
int dlist = 0;
int variable_alpha = I->VariableAlphaFlag;
SphereRec *sp = sphereRecPtr;
while(c--) {
Vector3f *sp_dot = sp->dot;
int b, *q, *s;
if(variable_alpha)
glColor4f(v[0], v[1], v[2], v[3]);
else
glColor4f(v[0], v[1], v[2], alpha);
(*vptr)+=4; v = *vptr;
{
float vdw = v[3];
glTranslatef(v[0], v[1], v[2]);
if((vdw != last_vdw) || (!dlist)) {
last_vdw = vdw;
q = sp->Sequence;
s = sp->StripLen;
#ifndef PURE_OPENGL_ES_2
for(b = 0; b < sp->NStrip; b++) {
int d;
glBegin(GL_TRIANGLE_STRIP);
for(d = 0; d < (*s); d++) {
float *norm = sp_dot[*(q++)];
glNormal3fv(norm);
glVertex3f(vdw * norm[0], vdw * norm[1], vdw * norm[2]);
}
glEnd();
s++;
}
#endif
}
glTranslatef(-v[0], -v[1], -v[2]);
}
(*vptr)+=4; v = *vptr;
}
}
}
if (!ok){
CGOFree(I->shaderCGO);
I->shaderCGO = NULL;
I->R.fInvalidate(&I->R, I->R.cs, cRepInvPurge);
I->R.cs->Active[cRepSphere] = false;
}
return ok;
} }
//, float radius, int carg, float pixel_scale, int clamp_size_flag, float max _size){
static void RenderSphereMode_Sprites(PyMOLGlobals *G, RepSphere *I, #ifndef _PYMOL_NO_RAY
RenderInfo *info, int sphere_mode, int carg, float **vptr, float **vnptr) static int RepSphereRenderRay(PyMOLGlobals *G, RepSphere * I, RenderInfo * info)
{
int c = carg;
float pixel_scale = 1.0F / info->vertex_scale;
float last_radius = -1.0F, cur_radius;
float size;
float *v = *vptr, *vn = *vnptr;
float max_size =
SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting,
cSetting_sphere_point_max_size);
int clamp_size_flag = (max_size >= 0.0F);
if((sphere_mode == 3) || (sphere_mode == 8)) {
pixel_scale *= 2.0F;
glEnable(GL_POINT_SMOOTH);
glAlphaFunc(GL_GREATER, 0.5F);
glEnable(GL_ALPHA_TEST);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glPointSize(1.0F);
} else {
glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
glDisable(GL_POINT_SMOOTH);
glDisable(GL_ALPHA_TEST);
pixel_scale *= 1.4F;
}
if((sphere_mode == 7) || (sphere_mode == 8))
glEnable(GL_LIGHTING);
glBegin(GL_POINTS);
while(c--) {
if(last_radius != (cur_radius = v[7])) {
size = cur_radius * pixel_scale;
glEnd();
if(clamp_size_flag)
if(size > max_size)
size = max_size;
glPointSize(size);
glBegin(GL_POINTS);
last_radius = cur_radius;
}
glColor3fv(v);
(*vptr)+=4; v = *vptr;
if(vn) {
glNormal3fv(vn);
(*vnptr)+=3; vn = *vnptr;
}
glVertex3fv(v);
(*vptr)+=4; v = *vptr;
}
glEnd();
if(sphere_mode == 3) {
glDisable(GL_POINT_SMOOTH);
glAlphaFunc(GL_GREATER, 0.05F);
} else {
glEnable(GL_ALPHA_TEST);
}
}
static void RenderSphereMode_Points(PyMOLGlobals *G, RepSphere *I, RenderInfo *i
nfo, int carg){
#ifndef PURE_OPENGL_ES_2
float _1 = 1.0F;
float _2 = 2.0F;
float pixel_scale = 1.0F / info->vertex_scale;
int repeat = true;
float x_add = 0.0F, y_add = 0.0F, z_add = 0.0F;
float z_factor = 0.0F, r_factor = 1.0F;
float largest;
float r, g, b;
float s_factor = 0.0F;
float zz_factor;
float clamp_radius;
float last_size;
int pass = 0;
float *v, last_radius, cur_radius, size;
int c;
float max_size =
SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting,
cSetting_sphere_point_max_size);
int clamp_size_flag = (max_size >= 0.0F);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_ALPHA_TEST);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glPointSize(1.0F);
pixel_scale *= 2.0F;
while(repeat) {
v = I->VC;
c = I->NC;
largest = 0.0F;
zz_factor = _1 - (float) pow(_1 - z_factor, 2);
if(zz_factor < 0.45F)
zz_factor = 0.45F;
last_radius = -1.0F;
last_size = -1.0F;
repeat = false;
glBegin(GL_POINTS);
while(c--) {
if(last_radius != (cur_radius = v[7])) {
size = cur_radius * pixel_scale;
clamp_radius = cur_radius;
if(clamp_size_flag)
if(size > max_size) {
size = max_size;
clamp_radius = size / pixel_scale;
}
size *= r_factor;
if(size != last_size) {
glEnd();
if(size > largest)
largest = size;
if(size < _2) {
if(!pass) {
zz_factor = 1.0F;
s_factor = 0.0F;
}
}
if(size < _1) {
size = _1;
glDisable(GL_POINT_SMOOTH);
glDisable(GL_ALPHA_TEST);
} else {
glEnable(GL_POINT_SMOOTH);
glEnable(GL_ALPHA_TEST);
}
glPointSize(size);
glBegin(GL_POINTS);
}
x_add = z_factor * clamp_radius * info->view_normal[0];
y_add = z_factor * clamp_radius * info->view_normal[1];
z_add = z_factor * clamp_radius * info->view_normal[2];
last_radius = cur_radius;
last_size = size;
}
r = zz_factor * v[0] + s_factor;
g = zz_factor * v[1] + s_factor;
b = zz_factor * v[2] + s_factor;
glColor3f(r > _1 ? _1 : r, g > _1 ? _1 : g, b > _1 ? _1 : b);
v += 4;
glVertex3f(v[0] + x_add, v[1] + y_add, v[2] + z_add);
v += 4;
}
glEnd();
if(largest > 2.0F) {
float reduce = (largest - 2.0F) / largest;
r_factor *= reduce;
z_factor = (float) sqrt1f(1.0F - (r_factor * r_factor));
s_factor = (float) pow(z_factor, 20.0F) * 0.5F;
repeat = true;
pass++;
}
}
glDisable(GL_POINT_SMOOTH);
#endif
}
static void RenderSphereMode_9(PyMOLGlobals *G, RepSphere *I, RenderInfo *info,
float **vptr, int carg){
int c = carg;
short use_shader;
float *v = *vptr;
use_shader = SettingGetGlobal_b(G, cSetting_sphere_use_shader) &
SettingGetGlobal_b(G, cSetting_use_shaders);
if (I->shaderCGO && !use_shader){
CGOFree(I->shaderCGO);
I->shaderCGO = 0;
}
if (use_shader){
if (!I->shaderCGO){
I->shaderCGO = CGONew(G);
I->shaderCGO->use_shader = true;
// generating shader
#ifndef PURE_OPENGL_ES_2
CGOEnable(I->shaderCGO, GL_LIGHTING);
#endif
while (c--) {
CGOAlpha(I->shaderCGO, v[3]);
CGOColorv(I->shaderCGO, v);
CGOSphere(I->shaderCGO, v+4, v[7]);
(*vptr)+=8; v = *vptr;
}
CGOStop(I->shaderCGO);
{
CGO *convertcgo = NULL;
convertcgo = CGOOptimizeSpheresToVBONonIndexed(I->shaderCGO, 0, true);
if (convertcgo){
CGOFree(I->shaderCGO);
I->shaderCGO = convertcgo;
}
}
}
if (I->shaderCGO){
I->shaderCGO->enable_shaders = true;
CGORenderGL(I->shaderCGO, NULL, NULL, NULL, info, &I->R);
}
}
}
#ifdef _PYMOL_ARB_SHADERS
void RenderSphereMode_ARB(PyMOLGlobals *G, RenderInfo *info, float **vptr, int c
arg){
int c = carg;
float fog_info[3];
float nv[4];
float z_front, z_back;
float *v = *vptr;
float last_radius, cur_radius;
RenderSpherePopulateVariables(G, info, nv, fog_info, &z_front, &z_back);
if(Feedback(G, FB_OpenGL, FB_Debugging))
PyMOLCheckOpenGLErr("before shader");
CShaderPrg_Enable_SphereShaderARB(G);
{
glNormal3fv(info->view_normal);
(*vptr)+=4; v = *vptr;
last_radius = -1.f;
glBegin(GL_QUADS);
while(c--) {
RepSphereRenderOneSphere_ARB(G, info, v - 4, &last_radius, &cur_radius, fo
g_info, v);
(*vptr)+=8; v = *vptr;
}
glEnd();
CShaderPrg_DisableARB(sphereARBShaderPrg);
if(Feedback(G, FB_OpenGL, FB_Debugging))
PyMOLCheckOpenGLErr("after shader");
}
}
#endif
/* simple, default point width points -- modes 1 or 6 */
static void RenderSphereMode_1_or_6(PyMOLGlobals *G, RepSphere *I,
RenderInfo *info, float **vptr, float **vnptr, int carg, float alpha)
{
#ifndef PURE_OPENGL_ES_2
int c = carg;
float *v = *vptr, *vn = *vnptr;
glPointSize(SettingGet_f
(G, I->R.cs->Setting, I->R.obj->Setting,
cSetting_sphere_point_size));
glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
glDisable(GL_POINT_SMOOTH);
glDisable(GL_ALPHA_TEST);
glBegin(GL_POINTS);
if(alpha == 1.0) {
if(vn) {
glEnd();
glEnable(GL_LIGHTING);
glBegin(GL_POINTS);
while(c--) {
glColor3fv(v);
(*vptr)+=4; v = *vptr;
glNormal3fv(vn);
(*vnptr)+=3; vn = *vnptr;
glVertex3fv(v);
(*vptr)+=4; v = *vptr;
}
} else {
while(c--) {
glColor3fv(v);
(*vptr)+=4; v = *vptr;
glVertex3fv(v);
(*vptr)+=4; v = *vptr;
}
}
} else {
if(vn) {
glEnd();
glEnable(GL_LIGHTING);
glBegin(GL_POINTS);
while(c--) {
glColor4f(v[0], v[1], v[2], alpha);
(*vptr)+=4; v = *vptr;
glNormal3fv(vn);
(*vnptr)+=3; vn = *vnptr;
glVertex3fv(v);
(*vptr)+=4; v = *vptr;
}
} else {
while(c--) {
glColor4f(v[0], v[1], v[2], alpha);
(*vptr)+=4; v = *vptr;
glVertex3fv(v);
(*vptr)+=4; v = *vptr;
}
}
}
glEnd();
glEnable(GL_ALPHA_TEST);
#endif
}
static void RepSpheresPrepPickingIfNoSphereGeometry(RepSphere * I,
int sphere_mode, float *pixel_scale)
{
PyMOLGlobals *G = I->R.G;
switch (sphere_mode) {
case 2:
case 7:
(*pixel_scale) *= 1.4F;
glPointSize(1.0F);
break;
case 3:
case 8:
(*pixel_scale) *= 2.0F;
glPointSize(1.0F);
break;
default:
{
float ptsize = SettingGet_f
(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_sphere_point_size);
glPointSize(ptsize);
}
break;
}
}
static void RepSpheresSetColorForPicking(RepSphere * I, Picking **pick, int *i,
int *j, Pickable **p){
(*i)++;
if(!(*pick)[0].src.bond) {
/* pass 1 - low order bits * */
glColor3ub((uchar) ((*i & 0xF) << 4), (uchar) ((*i & 0xF0) | 0x8),
(uchar) ((*i & 0xF00) >> 4));
VLACheck((*pick), Picking, *i);
(*p)++;
(*pick)[*i].src = **p; /* copy object and atom info */
(*pick)[*i].context = I->R.context;
} else {
/* pass 2 - high order bits */
(*j) = *i >> 12;
glColor3ub((uchar) ((*j & 0xF) << 4), (uchar) ((*j & 0xF0) | 0x8),
(uchar) ((*j & 0xF00) >> 4));
}
}
static void RepSpheresRenderSphereGeometryForPicking(SphereRec *sp, float *v0, f
loat vdw){
int *s, *q, b, cc;
q = sp->Sequence;
s = sp->StripLen;
for(b = 0; b < sp->NStrip; b++) {
#ifdef PURE_OPENGL_ES_2
/* TODO */
#else
glBegin(GL_TRIANGLE_STRIP);
for(cc = 0; cc < (*s); cc++) {
glNormal3f(sp->dot[*q][0], sp->dot[*q][1], sp->dot[*q][2]);
glVertex3f(v0[0] + vdw * sp->dot[*q][0],
v0[1] + vdw * sp->dot[*q][1],
v0[2] + vdw * sp->dot[*q][2]);
q++;
}
glEnd();
#endif
s++;
}
}
static void RepSpheresRenderSphereRecAtVertex(SphereRec *sp, float *v0, float vd
w){
#ifndef PURE_OPENGL_ES_2
Vector3f *sp_dot = sp->dot;
int b, *q, *s;
{
glTranslatef(v0[0], v0[1], v0[2]);
q = sp->Sequence;
s = sp->StripLen;
for(b = 0; b < sp->NStrip; b++) {
int d;
glBegin(GL_TRIANGLE_STRIP);
for(d = 0; d < (*s); d++) {
float *norm = sp_dot[*(q++)];
glNormal3fv(norm);
glVertex3f(vdw * norm[0], vdw * norm[1], vdw * norm[2]);
}
glEnd();
s++;
}
glTranslatef(-v0[0], -v0[1], -v0[2]);
}
#endif
}
static void RepSpheresRenderPointForPicking(RepSphere * I, float vdw, float *v,
int sphere_mode, float *last_radius, float *cur_radius, float pixel_scale,
int clamp_size_flag, float max_size, short *hasBegun)
{
#ifndef PURE_OPENGL_ES_2
float size;
float *v0 = &v[4];
SphereRec *sp = I->R.G->Sphere->Sphere[0];
switch (sphere_mode) {
case -1:
case 0: /* memory-efficient sphere rendering */
if(I->SSP) {
sp = I->SSP;
}
RepSpheresRenderSphereRecAtVertex(sp, v0, vdw);
break;
case 2:
case 3:
case 4:
case 5:
case 7:
case 8:
{
{
(*cur_radius) = v[7];
size = (*cur_radius) * pixel_scale;
if (*hasBegun){
glEnd();
(*hasBegun) = 0;
}
if(clamp_size_flag)
if(size > max_size)
size = max_size;
glPointSize(size);
glBegin(GL_POINTS);
(*hasBegun) = 1;
*last_radius = *cur_radius;
}
}
glVertex3fv(v0);
break;
default: /* simple, default point width points */
glVertex3fv(v0);
break;
}
#endif
}
static void RepSpheresRenderEndOfPicking(int sphere_mode){
switch (sphere_mode) {
case -1:
case 0:
break;
case 3:
case 4:
case 8:
glDisable(GL_POINT_SMOOTH);
glAlphaFunc(GL_GREATER, 0.05F);
break;
default:
glEnable(GL_ALPHA_TEST);
break;
}
}
static int RepSphereRenderRay(RepSphere * I, RenderInfo * info, float alpha)
{ {
CRay *ray = info->ray; CRay *ray = info->ray;
SphereRec *sp = I->SP; float alpha = 1.0F -
int ok = true; SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_sphere_transpa
int c = I->N; rency);
int cc = 0; if(fabs(alpha - 1.0) < R_SMALL4)
float *v = I->V, *vc; alpha = 1.0F;
int a;
ray->transparentf(1.0 - alpha); ray->transparentf(1.0 - alpha);
if(I->spheroidFlag) { if (I->spheroidCGO){
if(sp) { CGORenderRay(I->spheroidCGO, ray, info, NULL, NULL, I->R.cs->Setting, I->R.o
while(c--) { bj->Setting);
vc = v;
v += 3;
for(a = 0; ok && a < sp->NStrip; a++) {
cc = sp->StripLen[a];
while(ok && (cc--) > 2) {
ok &= ray->triangle3fv(v + 3, v + 9, v + 15, v, v + 6, v + 12, vc, vc
, vc);
v += 6;
}
v += 12;
}
}
}
} else { } else {
int variable_alpha = I->VariableAlphaFlag; CGORenderRay(I->primitiveCGO, ray, info, NULL, NULL, I->R.cs->Setting, I->R.
v = I->VC; obj->Setting);
c = I->NC;
while(ok && c--) {
if(variable_alpha) {
ray->transparentf(1.0F - v[3]);
}
ray->color3fv(v);
v += 4;
ok &= ray->sphere3fv(v, *(v + 3));
v += 4;
}
} }
ray->transparentf(0.0); ray->transparentf(0.0);
return ok; return true;
} }
#endif
static void RepSphereRenderPick(RepSphere * I, RenderInfo * info, float alpha, i nt sphere_mode) static void RepSphereRenderPick(RepSphere * I, RenderInfo * info, int sphere_mod e)
{ {
PyMOLGlobals *G = I->R.G; PyMOLGlobals *G = I->R.G;
SphereRec *sp = NULL;
Picking **pick = info->pick;
int c = I->N;
float *v = I->V;
int a;
int cc = 0;
int trans_pick_mode = SettingGet_i(G, I->R.cs->Setting,
I->R.obj->Setting,
cSetting_transparency_picking_mode);
switch (sphere_mode){
case 0: case 4: case 5: case 9:
// for picking these modes, use geometry
sp = I->R.G->Sphere->Sphere[0];
}
SceneSetupGLPicking(G);
if(I->R.P && ((trans_pick_mode == 1) || ((trans_pick_mode == 2) && (alpha > 0.
9F)))) {
int i, j;
Pickable *p;
i = (*pick)->src.index;
p = I->R.P;
if(I->spheroidFlag && sp) {
while(c--) {
int skip = (p[1].index < 0);
if(!skip) {
RepSpheresSetColorForPicking(I, pick, &i, &j, &p);
} else {
p++;
}
v += 4; if (!I->renderCGO){
for(a = 0; a < sp->NStrip; a++) { // only for sphere_mode 5, where we don't use a renderCGO (yet) ARB: immedia
cc = sp->StripLen[a]; te mode GL_QUADS
if(!skip) { short use_shader = SettingGetGlobal_b(G, cSetting_sphere_use_shader) &&
glBegin(GL_TRIANGLE_STRIP); SettingGetGlobal_b(G, cSetting_use_shaders);
while((cc--) > 0) { CGO *convertcgo = CGOSimplify(I->primitiveCGO, 0, 0);
glNormal3fv(v); CGO *convertcgo2 = CGOCombineBeginEnd(convertcgo, 0);
glVertex3fv(v + 3); if (use_shader){
v += 6; I->renderCGO = CGOOptimizeToVBONotIndexed(convertcgo2, 0);
} CGOFree(convertcgo2);
glEnd();
} else {
while((cc--) > 0) {
v += 6;
}
}
}
}
} else { } else {
float last_radius = -1.0F; I->renderCGO = convertcgo2;
float cur_radius;
float pixel_scale = 1.0F / info->vertex_scale;
float max_size = SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting,
cSetting_sphere_point_max_size) * 3;
int clamp_size_flag = (max_size >= 0.0F);
short hasBegun = 0;
if(!sp) {
RepSpheresPrepPickingIfNoSphereGeometry(I, sphere_mode, &pixel_scale);
glBegin(GL_POINTS);
hasBegun = 1;
}
v = I->VC;
c = I->NC;
while(c--) {
int skip = (p[1].index < 0);
if(!skip) {
RepSpheresSetColorForPicking(I, pick, &i, &j, &p);
if(sp) {
RepSpheresRenderSphereGeometryForPicking(sp, v + 4, v[7] );
} else {
RepSpheresRenderPointForPicking(I, v[7], v, sphere_mode, &last_radius
, &cur_radius, pixel_scale, clamp_size_flag, max_size, &hasBegun);
}
} else {
p++;
}
v += 8;
}
if(!sp) {
glEnd();
RepSpheresRenderEndOfPicking(sphere_mode);
}
} }
(*pick)[0].src.index = i; I->renderCGO->use_shader = use_shader;
CGOFree(convertcgo);
} }
CGORenderGLPicking(I->renderCGO, info, &I->R.context, I->R.cs->Setting, I->R.o bj->Setting);
} }
static void RepSphereRender(RepSphere * I, RenderInfo * info) static int RepGetSphereMode(PyMOLGlobals *G, RepSphere * I, bool use_shader){
{
CRay *ray = info->ray;
Picking **pick = info->pick;
PyMOLGlobals *G = I->R.G;
float *v = I->V, *vn = I->VN;
int c = I->N;
SphereRec *sp = I->SP;
float alpha;
int ok = true;
short use_shader = SettingGetGlobal_b(G, cSetting_sphere_use_shader) &
SettingGetGlobal_b(G, cSetting_use_shaders);
int sphere_mode = SettingGet_i(G, I->R.cs->Setting, int sphere_mode = SettingGet_i(G, I->R.cs->Setting,
I->R.obj->Setting, I->R.obj->Setting,
cSetting_sphere_mode); cSetting_sphere_mode);
if (sphere_mode == 4) // sphere_mode 4 no longer exists, use default
if (!ray) { sphere_mode = -1;
switch (sphere_mode) { switch (sphere_mode) {
case 5: case 5:
#ifdef _PYMOL_ARB_SHADERS #ifdef _PYMOL_ARB_SHADERS
if (!sphereARBShaderPrg && G->HaveGUI && G->ValidContext) { if (!sphereARBShaderPrg && G->HaveGUI && G->ValidContext) {
sphereARBShaderPrg = CShaderPrg_NewARB(G, "sphere_arb", sphere_arb_vs, sp sphereARBShaderPrg = CShaderPrg::NewARB(G, "sphere_arb",
here_arb_fs); G->ShaderMgr->GetShaderSource("sph
ere_arb_vs.vs"),
G->ShaderMgr->GetShaderSource("sph
ere_arb_fs.fs"));
} }
if (!sphereARBShaderPrg) if (!sphereARBShaderPrg)
#endif #endif
{ {
PRINTFB(G, FB_ShaderMgr, FB_Warnings) PRINTFB(G, FB_ShaderMgr, FB_Warnings)
" Warning: ARB shaders (sphere_mode=5) not supported.\n" ENDFB(G); " Warning: ARB shaders (sphere_mode=5) not supported.\n" ENDFB(G);
if (!use_shader || !G->ShaderMgr->ShaderPrgExists("sphere")) {
sphere_mode = 9; sphere_mode = 9;
} else {
sphere_mode = 0;
}
} }
break; break;
case -1: case -1:
sphere_mode = 9; sphere_mode = 9;
case 9: case 9:
if (!use_shader || !CShaderMgr_ShaderPrgExists(G->ShaderMgr, "sphere")) { if (!use_shader || !G->ShaderMgr->ShaderPrgExists("sphere")) {
sphere_mode = 0; sphere_mode = 0;
} }
} }
} return sphere_mode;
alpha = }
SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_sphere_transpa
rency); static void RepSphereRender(RepSphere * I, RenderInfo * info)
alpha = 1.0F - alpha; {
if(fabs(alpha - 1.0) < R_SMALL4) CRay *ray = info->ray;
alpha = 1.0F; Picking **pick = info->pick;
PyMOLGlobals *G = I->R.G;
int ok = true;
bool use_shader = SettingGetGlobal_b(G, cSetting_sphere_use_shader) &&
SettingGetGlobal_b(G, cSetting_use_shaders);
if(ray) { if(ray) {
ok &= RepSphereRenderRay(I, info, alpha); #ifndef _PYMOL_NO_RAY
} else if(G->HaveGUI && G->ValidContext) { ok &= RepSphereRenderRay(G, I, info);
#endif
return;
}
int sphere_mode = RepGetSphereMode(G, I, use_shader);
if(G->HaveGUI && G->ValidContext) {
if(pick) { if(pick) {
RepSphereRenderPick(I, info, alpha, sphere_mode); RepSphereRenderPick(I, info, sphere_mode);
} else { /* not pick */ } else { /* not pick, render! */
if(!sp) {
/* no sp -- we're rendering as points */
v = I->VC;
c = I->NC;
I->LastVertexScale = info->vertex_scale;
if((sphere_mode > 0) && (!info->line_lighting))
glDisable(GL_LIGHTING);
switch (sphere_mode) {
case -1:
case 0: /* memory-efficient sphere rendering */
if (ok)
ok &= RenderSphereMode_Direct(G, I, info, c, &v, alpha, I->SSP);
break;
case 2:
case 3:
case 7:
case 8:
RenderSphereMode_Sprites(G, I, info, sphere_mode, c, &v, &vn);
break;
case 4:
RenderSphereMode_Points(G, I, info, c);
break;
case 5: /* use vertex/fragment program */
#ifdef _PYMOL_ARB_SHADERS #ifdef _PYMOL_ARB_SHADERS
RenderSphereMode_ARB(G, info, &v, c); if (sphere_mode == 5){
break; // we need to check sphere_mode 5 here until
// we implement the CGO ARB operation, since
// picking uses the I->renderCGO
RepSphere_Generate_ARB_Spheres(G, I, info);
return; // sphere_mode 5 does not use I->renderCGO yet
}
#endif #endif
case 9: // use GLSL shader if (I->renderCGO){
RenderSphereMode_9(G, I, info, &v, c); if (I->renderCGO->use_shader != use_shader){
break; CGOFree(I->renderCGO);
default: I->renderCGO = 0;
RenderSphereMode_1_or_6(G, I, info, &v, &vn, c, alpha); } else {
break; CGORenderGL(I->renderCGO, NULL, NULL, NULL, info, &I->R);
} return;
glEnable(GL_LIGHTING); }
} else { /* real spheres, drawn with triangles -- not poi
nts or impostors */
ok &= RenderSphereMode_Direct(G, I, info, c, &v, alpha, I->SSP);
} }
// Generate renderCGO for sphere_mode
switch (sphere_mode) {
case 0: /* memory-efficient sphere rendering */
RepSphere_Generate_Triangles(G, I, info);
break;
case 9: // use GLSL impostor shader
RepSphere_Generate_Impostor_Spheres(G, I, info);
break;
default:
// sphere_modes 1,2,3,6,7,8
RepSphere_Generate_Point_Sprites(G, I, info, sphere_mode);
break;
}
CHECKOK(ok, I->renderCGO);
if (!ok){
CGOFree(I->renderCGO);
I->R.fInvalidate(&I->R, I->R.cs, cRepInvPurge);
I->R.cs->Active[cRepSphere] = false;
}
if (I->renderCGO)
CGORenderGL(I->renderCGO, NULL, NULL, NULL, info, &I->R);
} }
} }
} }
int RepSphereSameVis(RepSphere * I, CoordSet * cs) int RepSphereSameVis(RepSphere * I, CoordSet * cs)
{ {
int *lv, *lc; bool *lv;
int *lc;
int a; int a;
AtomInfoType *ai; AtomInfoType *ai;
if(I->LastVisib && I->LastColor) { if(I->LastVisib && I->LastColor) {
lv = I->LastVisib; lv = I->LastVisib;
lc = I->LastColor; lc = I->LastColor;
for(a = 0; a < cs->NIndex; a++) { for(a = 0; a < cs->NIndex; a++) {
ai = cs->getAtomInfo(a); ai = cs->getAtomInfo(a);
if(*(lv++) != GET_BIT(ai->visRep, cRepSphere)) { if(*(lv++) != GET_BIT(ai->visRep, cRepSphere)) {
return false; return false;
skipping to change at line 1377 skipping to change at line 264
if(*(lc++) != ai->color) { if(*(lc++) != ai->color) {
return false; return false;
} }
} }
} else { } else {
return false; return false;
} }
return true; return true;
} }
static int RadiusOrder(float *list, int a, int b)
{
return (list[a * 8 + 7] <= list[b * 8 + 7]);
}
static bool RepSphereDetermineAtomVisibility(PyMOLGlobals *G, static bool RepSphereDetermineAtomVisibility(PyMOLGlobals *G,
AtomInfoType *ati1, int cartoon_side_chain_helper, int ribbon_side_chain_hel per) AtomInfoType *ati1, int cartoon_side_chain_helper, int ribbon_side_chain_hel per)
{ {
if (!(ati1->flags & cAtomFlag_polymer)) if (!(ati1->flags & cAtomFlag_polymer))
return true; return true;
bool sc_helper = bool sc_helper =
(GET_BIT(ati1->visRep, cRepCartoon) && (GET_BIT(ati1->visRep, cRepCartoon) &&
AtomSettingGetWD(G, ati1, cSetting_cartoon_side_chain_helper, cartoon_side_ chain_helper)) || AtomSettingGetWD(G, ati1, cSetting_cartoon_side_chain_helper, cartoon_side_ chain_helper)) ||
(GET_BIT(ati1->visRep, cRepRibbon) && (GET_BIT(ati1->visRep, cRepRibbon) &&
skipping to change at line 1414 skipping to change at line 296
return false; return false;
} else if(prot1 == cAN_C) { } else if(prot1 == cAN_C) {
if(ati1->name == G->lex_const.C) if(ati1->name == G->lex_const.C)
return false; return false;
} }
} }
return true; return true;
} }
static void RepSphereAddAtomVisInfoToStoredVC(RepSphere *I, ObjectMolecule *obj, static void RepSphereAddAtomVisInfoToStoredVC(RepSphere *I, ObjectMolecule *obj,
CoordSet * cs, int state, float *varg, int a1, AtomInfoType *ati1, int a, CoordSet * cs, int state, int a1, AtomInfoType *ati1, int a,
int *mf, float sphere_scale, int sphere_color, float transp, float sphere_scale, int sphere_color, float transp,
int *variable_alpha, float sphere_add) int *variable_alpha, float sphere_add)
{ {
PyMOLGlobals *G = cs->State.G; PyMOLGlobals *G = cs->State.G;
float at_transp = transp; float at_transp = transp;
int c1; int c1;
float *v0, *vc; float *v0, vc[3];
float *v = varg; const float *vcptr;
float at_sphere_scale = AtomSettingGetWD(G, ati1, cSetting_sphere_scale, spher e_scale); float at_sphere_scale = AtomSettingGetWD(G, ati1, cSetting_sphere_scale, spher e_scale);
int at_sphere_color = AtomSettingGetWD(G, ati1, cSetting_sphere_color, sphere_ color); int at_sphere_color = AtomSettingGetWD(G, ati1, cSetting_sphere_color, sphere_ color);
if(AtomSettingGetIfDefined(G, ati1, cSetting_sphere_transparency, &at_transp)) if(AtomSettingGetIfDefined(G, ati1, cSetting_sphere_transparency, &at_transp))
*variable_alpha = true; *variable_alpha = true;
if(I->R.P) { CGOPickColor(I->primitiveCGO, a1, ati1->masked ? cPickableNoPick : cPickableAt
I->NP++; om);
if(!ati1->masked) {
I->R.P[I->NP].index = a1;
} else {
I->R.P[I->NP].index = -1;
}
I->R.P[I->NP].bond = -1;
}
*mf = true;
I->NC++;
if(at_sphere_color == -1) if(at_sphere_color == -1)
c1 = ati1->color; c1 = ati1->color;
else else
c1 = at_sphere_color; c1 = at_sphere_color;
v0 = cs->Coord + 3 * a; v0 = cs->Coord + 3 * a;
if(ColorCheckRamped(G, c1)) { if(ColorCheckRamped(G, c1)) {
ColorGetRamped(G, c1, v0, v, state); ColorGetRamped(G, c1, v0, vc, state);
v += 3; vcptr = vc;
} else { } else {
vc = ColorGet(G, c1); /* save new color */ vcptr = ColorGet(G, c1); /* save new color */
*(v++) = *(vc++);
*(v++) = *(vc++);
*(v++) = *(vc++);
} }
*(v++) = 1.0F - at_transp; float alpha = 1.0F - at_transp;
CGOAlpha(I->primitiveCGO, alpha);
*(v++) = *(v0++); /* coordinate */ CGOColorv(I->primitiveCGO, vcptr);
*(v++) = *(v0++); float radius = obj->AtomInfo[a1].vdw * at_sphere_scale + sphere_add;
*(v++) = *(v0++); CGOSphere(I->primitiveCGO, v0, radius);
*(v++) = obj->AtomInfo[a1].vdw * at_sphere_scale + sphere_add; /* radius */
} }
static int RepSphereComputeSphereNormals(RepSphere *I){ /* This function is extraneous to do every time
PyMOLGlobals *G = I->R.G; we need to compute normals for RepSphere */
float range = 6.0F; static float SphereComputeCutMultiplier(SphereRec *sr){
float *vc = I->VC;
float *dot = G->Sphere->Sphere[1]->dot[0];
int n_dot = G->Sphere->Sphere[1]->nDot;
int nc = I->NC;
int *active = NULL;
float *v_tmp = NULL;
int ok = true;
int a; int a;
MapType *map = NULL; float *dot = sr->dot[0];
float *v0, *v; int n_dot = sr->nDot;
active = Alloc(int, 2 * n_dot);
CHECKOK(ok, active);
if (ok)
v_tmp = Alloc(float, 3 * nc);
CHECKOK(ok, v_tmp);
if (ok) {
float *src = vc + 4;
float *dst = v_tmp;
for(a = 0; a < nc; a++) { /* create packed array of sphere centers */
*(dst++) = *(src++);
*(dst++) = *(src++);
*(dst++) = *(src++);
src += 5;
}
{
map = MapNew(G, range, v_tmp, nc, NULL);
CHECKOK(ok, map);
if (ok)
I->VN = Alloc(float, I->NC * 3);
CHECKOK(ok, I->VN);
if(ok && map && I->VN) {
float dst;
float *vv;
int nbr_flag;
int n_dot_active, *da;
float cut_mult = -1.0F; float cut_mult = -1.0F;
float range2 = range * range;
ok &= MapSetupExpress(map);
if (ok){
v = vc + 4;
v0 = I->VN;
for(a = 1; a < n_dot; a++) { for(a = 1; a < n_dot; a++) {
float t_dot = dot_product3f(dot, dot + a * 3); float t_dot = dot_product3f(dot, dot + a * 3);
if(cut_mult < t_dot) if(cut_mult < t_dot)
cut_mult = t_dot; cut_mult = t_dot;
} }
} return cut_mult;
for(a = 0; ok && a < nc; a++) { }
/*
* for the spheroid implementation, this function sets color
* and pickcolor in the CGO given the atom idx
*
*/
static void RepSphereCGOSetSphereColorAndPick(ObjectMolecule *obj, CoordSet * cs
, CGO *cgo, int idx, int state, float transp, int sphere_color){
PyMOLGlobals *G = obj->Obj.G;
int a1 = cs->IdxToAtm[idx];
float at_transp;
AtomInfoType *ati1 = obj->AtomInfo + a1;
int at_sphere_color = AtomSettingGetWD(G, ati1, cSetting_sphere_color, sphere_
color);
if(AtomSettingGetIfDefined(G, ati1, cSetting_sphere_transparency, &at_transp))
{
float alpha = 1.0F - at_transp;
CGOAlpha(cgo, alpha);
}
int c1;
if(at_sphere_color == -1)
c1 = ati1->color;
else
c1 = at_sphere_color;
if(ColorCheckRamped(G, c1)) {
float *v0 = cs->Coord + 3 * idx;
float color[3];
ColorGetRamped(G, c1, v0, color, state);
CGOColorv(cgo, color);
} else {
const float *color = ColorGet(G, c1); /* save new color */
CGOColorv(cgo, color);
}
}
static
CGO *RepSphereGeneratespheroidCGO(ObjectMolecule * I, CoordSet *cs, SphereRec *s
p, int state){
int idx, a, b, c;
int *q, *s;
bool ok = true;
float spheroid_scale =
SettingGet_f(I->Obj.G, cs->Setting, I->Obj.Setting, cSetting_spheroid_scale)
;
int sphere_color =
SettingGet_color(I->Obj.G, cs->Setting, I->Obj.Setting, cSetting_sphere_colo
r);
float transp = SettingGet_f(I->Obj.G, cs->Setting, I->Obj.Setting, cSetting_sp
here_transparency);
CGO *cgo = CGONew(I->Obj.G);
for(idx = 0; idx < cs->NIndex; idx++) {
float *v0 = &cs->Coord[3 * idx];
a = cs->IdxToAtm[idx];
q = sp->Sequence;
s = sp->StripLen;
RepSphereCGOSetSphereColorAndPick(I, cs, cgo, idx, state, transp, sphere_col
or);
for(b = 0; ok && b < sp->NStrip; b++) {
float *sphLen = cs->Spheroid + (sp->nDot * a);
float *sphNorm = cs->SpheroidNormal + (3 * sp->nDot * a);
CGOBegin(cgo, GL_TRIANGLE_STRIP);
for(c = 0; c < (*s); c++) {
float sphTmp, *sphTmpN = sphNorm + 3 * (*q);
CGONormalv(cgo, sphTmpN);
sphTmp = (*(sphLen + (*q))) * spheroid_scale;
// point
CGOVertex(cgo, v0[0] + sphTmp * sp->dot[*q][0],
v0[1] + sphTmp * sp->dot[*q][1],
v0[2] + sphTmp * sp->dot[*q][2]);
q++;
}
CGOEnd(cgo);
s++;
ok &= !I->Obj.G->Interrupt;
}
}
CGOStop(cgo);
if (!ok){
CGOFree(cgo);
}
return cgo;
}
/*
* when normals are needed (sphere_mode 6-8),
* this function computes the normal for an atom
* and pickcolor in the CGO given the atom idx
*
*/
static void RepSphereSetNormalForSphere(RepSphere *I, MapType *map, float *v_tmp
,
float *v, float cut_mult, int a,
int *active, float *dot, int n_dot){
int h, k, l, b, i, j; int h, k, l, b, i, j;
float v1[3]; float v1[3];
nbr_flag = false; int n_dot_active, *da;
float *vv;
float dst;
MapLocus(map, v, &h, &k, &l); MapLocus(map, v, &h, &k, &l);
da = active; da = active;
for(b = 0; b < n_dot; b++) { for(b = 0; b < n_dot; b++) {
*(da++) = b * 3; *(da++) = b * 3;
} }
n_dot_active = n_dot; n_dot_active = n_dot;
i = *(MapEStart(map, h, k, l)); i = *(MapEStart(map, h, k, l));
if(i) { if(i) {
j = map->EList[i++]; j = map->EList[i++];
while(ok && j >= 0) { while(j >= 0) {
if(j != a) { if(j != a) {
vv = v_tmp + 3 * j; vv = v_tmp + 3 * j;
if(within3fret(vv, v, range, range2, v1, &dst)) { if(within3fret(vv, v, SPHERE_NORMAL_RANGE, SPHERE_NORMAL_RANGE2, v1, &ds t)) {
float cutoff = dst * cut_mult; float cutoff = dst * cut_mult;
b = 0; b = 0;
while(b < n_dot_active) { while(b < n_dot_active) {
vv = dot + active[b]; vv = dot + active[b];
if(dot_product3f(v1, vv) > cutoff) { if(dot_product3f(v1, vv) > cutoff) {
n_dot_active--; n_dot_active--;
active[b] = active[n_dot_active]; active[b] = active[n_dot_active];
} }
b++; b++;
} }
} }
} }
j = map->EList[i++]; j = map->EList[i++];
ok &= !G->Interrupt;
} }
} }
if (ok){ float v0[3];
if(!n_dot_active) { if(!n_dot_active) {
v0[0] = 0.0F; v0[0] = 0.0F;
v0[1] = 0.0F; v0[1] = 0.0F;
v0[2] = 1.0F; v0[2] = 1.0F;
} else { } else {
zero3f(v0); zero3f(v0);
b = 0; b = 0;
while(b < n_dot_active) { while(b < n_dot_active) {
vv = dot + active[b]; vv = dot + active[b];
add3f(vv, v0, v0); add3f(vv, v0, v0);
b++; b++;
} }
normalize3f(v0); normalize3f(v0);
CGONormalv(I->primitiveCGO, v0);
} }
v += 8;
v0 += 3;
}
ok &= !G->Interrupt;
}
}
}
}
MapFree(map);
map = NULL;
FreeP(v_tmp);
map = NULL;
FreeP(active);
return ok;
}
static int RepSphereWriteSphereRecIntoArray(SphereRec *sp, int spheroidFlag,
CoordSet * cs, float **varg, int a1, float *v0, float vdw,
float spheroid_scale)
{
PyMOLGlobals *G = cs->State.G;
float *v = *varg;
int b, *q, *s, c, ok = true;
q = sp->Sequence;
s = sp->StripLen;
if(spheroidFlag) {
for(b = 0; ok && b < sp->NStrip; b++) {
float *sphLen = cs->Spheroid + (sp->nDot * a1);
float *sphNorm = cs->SpheroidNormal + (3 * sp->nDot * a1);
for(c = 0; c < (*s); c++) {
float sphTmp, *sphTmpN = sphNorm + 3 * (*q);
*(v++) = *(sphTmpN++);
*(v++) = *(sphTmpN++);
*(v++) = *(sphTmpN++);
sphTmp = (*(sphLen + (*q))) * spheroid_scale;
*(v++) = v0[0] + sphTmp * sp->dot[*q][0]; /* point */
*(v++) = v0[1] + sphTmp * sp->dot[*q][1];
*(v++) = v0[2] + sphTmp * sp->dot[*q][2];
q++;
}
s++;
ok &= !G->Interrupt;
}
} else {
for(b = 0; ok && b < sp->NStrip; b++) {
for(c = 0; ok && c < (*s); c++) {
*(v++) = sp->dot[*q][0]; /* normal */
*(v++) = sp->dot[*q][1];
*(v++) = sp->dot[*q][2];
*(v++) = v0[0] + vdw * sp->dot[*q][0]; /* point */
*(v++) = v0[1] + vdw * sp->dot[*q][1];
*(v++) = v0[2] + vdw * sp->dot[*q][2];
q++;
ok &= !G->Interrupt;
}
s++;
ok &= !G->Interrupt;
}
}
return ok;
}
/*
When Culling, triangles that are within other close spheres (i.e., within vdw p
lus solvent_radius),
then the triangles are not rendered. This saves geometry, but adds to calculat
ing these overlaps.
right now, it looks like these new strips are generated on the fly, this whole
RepSphere.c file could be
enhanced by CGOs (other than sphere_mode 9 which already uses them)
sphere_add - the setting solvent_radius
*/
static int RepSphereGenerateGeometryCullForSphere(SphereRec *sp,
ObjectMolecule *obj, CoordSet * cs, float **varg, MapType *map,
float vdw, float *v0, int *visFlag, int *marked, float sphere_scale,
int a, float sphere_add, int *nt)
{
PyMOLGlobals *G = cs->State.G;
float *v = *varg;
int ok = true;
int b;
int h, k, l, i, j, a2;
int *q, *s, c;
float v1[3];
short restart;
/* go through each vertex in the SphereRec, flag it to 0 if there are any coor
dinates
that are within the vdw * sphere_scale + solvent radius */
for(b = 0; ok && b < sp->nDot; b++) { /* Sphere culling mode - more stri
ps, but many fewer atoms */
v1[0] = v0[0] + vdw * sp->dot[b][0];
v1[1] = v0[1] + vdw * sp->dot[b][1];
v1[2] = v0[2] + vdw * sp->dot[b][2];
MapLocus(map, v1, &h, &k, &l);
visFlag[b] = 1;
i = *(MapEStart(map, h, k, l));
if(i) {
j = map->EList[i++];
while(j >= 0) {
a2 = cs->IdxToAtm[j];
if(marked[a2]) {
AtomInfoType *ati2 = obj->AtomInfo + a2;
float at2_sphere_scale = AtomSettingGetWD(G, ati2, cSetting_sphere_sca
le, sphere_scale);
if(j != a)
if(within3f(cs->Coord + 3 * j, v1,
ati2->vdw * at2_sphere_scale + sphere_add)) {
/* do not render atoms if there are atoms within this distance */
visFlag[b] = 0;
break;
}
}
j = map->EList[i++];
}
}
ok &= !G->Interrupt;
}
q = sp->Sequence;
s = sp->StripLen;
for(b = 0; ok && b < sp->NStrip; b++) {
/* this is an attempt to fill in *some* of the cracks
* by checking to see if the center of the triangle is visible
* IMHO - the increase in framerates is worth missing a triangle
* here or there, and the user can always turn off sphere culling */
q += 2;
for(c = 2; c < (*s); c++) {
float v1[3];
int q0, q1, q2, flag;
q0 = *q;
q1 = *(q - 1);
q2 = *(q - 2);
if((!visFlag[q0]) && (!visFlag[q1]) && (!visFlag[q2]))
v1[0] = v0[0] + vdw * sp->dot[q0][0];
v1[1] = v0[1] + vdw * sp->dot[q0][1];
v1[2] = v0[2] + vdw * sp->dot[q0][2];
v1[0] += v0[0] + vdw * sp->dot[q1][0];
v1[1] += v0[1] + vdw * sp->dot[q1][1];
v1[2] += v0[2] + vdw * sp->dot[q1][2];
v1[0] += v0[0] + vdw * sp->dot[q2][0];
v1[1] += v0[1] + vdw * sp->dot[q2][1];
v1[2] += v0[2] + vdw * sp->dot[q2][2];
v1[0] /= 3;
v1[1] /= 3;
v1[2] /= 3;
flag = true;
i = *(MapEStart(map, h, k, l));
if(i) {
j = map->EList[i++];
while(j >= 0) {
a2 = cs->IdxToAtm[j];
if(marked[a2]) {
if(j != a)
if(within3f
(cs->Coord + 3 * j, v1,
cs->Obj->AtomInfo[a2].vdw * sphere_scale + sphere_add)) {
flag = false;
break;
}
}
j = map->EList[i++];
}
}
if(flag) {
visFlag[q0] = 1;
visFlag[q1] = 1;
visFlag[q2] = 1;
}
q++;
}
s++;
ok &= !G->Interrupt;
}
*(nt) = 0; /* how many passes through the triangle renderer? */
q = sp->Sequence;
s = sp->StripLen;
for(b = 0; ok && b < sp->NStrip; b++) {
restart = true; /* startin a new strip */
for(c = 0; c < (*s); c++) {
if(c > 1) { /* on third vertex or better */
int q0, q1, q2;
q0 = *q; /* get the indices of the triangle in this strip */
q1 = *(q - 1);
q2 = *(q - 2);
if(visFlag[q0] || (visFlag[q1]) || (visFlag[q2])) { /* visible? */
*(v++) = restart; /* store continuing string flag */
if(restart) { /* not continuing...this is a new strip */
if(c & 0x1) /* make sure strip starts off "right" */
*(v - 1) = 2.0;
*(v++) = sp->dot[q2][0]; /* normal */
*(v++) = sp->dot[q2][1];
*(v++) = sp->dot[q2][2];
*(v++) = v0[0] + vdw * sp->dot[q2][0]; /* point */
*(v++) = v0[1] + vdw * sp->dot[q2][1];
*(v++) = v0[2] + vdw * sp->dot[q2][2];
*(v++) = sp->dot[q1][0]; /* normal */
*(v++) = sp->dot[q1][1];
*(v++) = sp->dot[q1][2];
*(v++) = v0[0] + vdw * sp->dot[q1][0]; /* point */
*(v++) = v0[1] + vdw * sp->dot[q1][1];
*(v++) = v0[2] + vdw * sp->dot[q1][2];
*(v++) = sp->dot[q0][0]; /* normal */
*(v++) = sp->dot[q0][1];
*(v++) = sp->dot[q0][2];
*(v++) = v0[0] + vdw * sp->dot[q0][0]; /* point */
*(v++) = v0[1] + vdw * sp->dot[q0][1];
*(v++) = v0[2] + vdw * sp->dot[q0][2];
} else { /* continue strip */
*(v++) = sp->dot[q0][0]; /* normal */
*(v++) = sp->dot[q0][1];
*(v++) = sp->dot[q0][2];
*(v++) = v0[0] + vdw * sp->dot[q0][0]; /* point */
*(v++) = v0[1] + vdw * sp->dot[q0][1];
*(v++) = v0[2] + vdw * sp->dot[q0][2];
}
restart = false;
(*nt)++;
} else {
restart = true; /* next triangle is a new strip */
}
}
q++;
}
s++;
ok &= !G->Interrupt;
}
return ok;
}
static int RepSphereGenerateGeometryForSphere(RepSphere *I, ObjectMolecule *obj,
CoordSet * cs, int state, int a1, AtomInfoType *ati1, int a,
float sphere_scale, int sphere_color, float spheroid_scale, float transp,
int *variable_alpha, float sphere_add, int spheroidFlag, SphereRec *sp,
int *visFlag, int *marked, MapType *map, int *nt, float **varg)
{
PyMOLGlobals *G = cs->State.G;
float *v = *varg;
float at_transp = transp;
int ok = true;
int c1;
float *v0;
float vdw;
float at_sphere_scale = AtomSettingGetWD(G, ati1, cSetting_sphere_scale, spher
e_scale);
int at_sphere_color = AtomSettingGetWD(G, ati1, cSetting_sphere_color, sphere_
color);
if(AtomSettingGetIfDefined(G, ati1, cSetting_sphere_transparency, &at_transp))
(*variable_alpha) = true;
if(at_sphere_color == -1)
c1 = ati1->color;
else
c1 = at_sphere_color;
v0 = cs->Coord + 3 * a;
vdw = ati1->vdw * at_sphere_scale + sphere_add;
if(ColorCheckRamped(G, c1)) {
ColorGetRamped(G, c1, v0, v, state);
v += 3;
} else {
float *vc = ColorGet(G, c1);
*(v++) = *(vc++);
*(v++) = *(vc++);
*(v++) = *(vc++);
}
*(v++) = 1.0F - at_transp; /* alpha */
if(I->cullFlag && (!spheroidFlag) && (sp)) {
ok &= RepSphereGenerateGeometryCullForSphere(sp, obj, cs, &v, map, vdw, v0,
visFlag, marked, sphere_scale, a, sphere_add, nt);
} else if(sp) {
ok &= RepSphereWriteSphereRecIntoArray(sp, spheroidFlag, cs, &v, a1, v0, vdw
, spheroid_scale);
} else if (ok) { /* if sp is null, then we're simply drawing po
ints */
*(v++) = v0[0];
*(v++) = v0[1];
*(v++) = v0[2];
}
I->N++;
*varg = v;
return ok;
} }
Rep *RepSphereNew(CoordSet * cs, int state) Rep *RepSphereNew(CoordSet * cs, int state)
{ {
PyMOLGlobals *G = cs->State.G; PyMOLGlobals *G = cs->State.G;
ObjectMolecule *obj; ObjectMolecule *obj;
int ok = true; int ok = true;
int a, a1; int a, a1;
float *v; bool *lv;
int *lv, *lc; int *lc;
SphereRec *sp = G->Sphere->Sphere[0];
int sphere_quality, *nt;
int *visFlag = NULL;
MapType *map = NULL;
AtomInfoType *ai2;
int spheroidFlag = false;
float spheroid_scale;
float sphere_scale, sphere_add = 0.f; float sphere_scale, sphere_add = 0.f;
int sphere_color; int sphere_color;
int *map_flag = NULL, *mf;
int cartoon_side_chain_helper = 0; int cartoon_side_chain_helper = 0;
int ribbon_side_chain_helper = 0; int ribbon_side_chain_helper = 0;
AtomInfoType *ati1; AtomInfoType *ati1;
int vis_flag;
int sphere_mode; int sphere_mode;
int *marked = NULL; bool *marked = NULL;
float transp; float transp;
int variable_alpha = false; int variable_alpha = false;
#ifdef _this_code_is_not_used short use_shader = SettingGetGlobal_b(G, cSetting_sphere_use_shader) &&
float vv0[3], vv1[3], vv2[3];
float tn[3], vt1[3], vt2[3], xtn[3], *tn0, *tn1, *tn2;
#endif
int draw_mode = SettingGetGlobal_i(G, cSetting_draw_mode);
int draw_quality = (((draw_mode == 1) || (draw_mode == -2) || (draw_mode == 2)
));
short use_shader = SettingGetGlobal_b(G, cSetting_sphere_use_shader) &
SettingGetGlobal_b(G, cSetting_use_shaders); SettingGetGlobal_b(G, cSetting_use_shaders);
// skip if not visible // skip if not visible
if(!cs->hasRep(cRepSphereBit)) if(!cs->hasRep(cRepSphereBit))
return NULL; return NULL;
OOCalloc(G, RepSphere); OOCalloc(G, RepSphere);
CHECKOK(ok, I); CHECKOK(ok, I);
if (!ok) if (!ok)
return NULL; return NULL;
obj = cs->Obj; obj = cs->Obj;
marked = Calloc(int, obj->NAtom); marked = Calloc(bool, obj->NAtom);
CHECKOK(ok, marked); CHECKOK(ok, marked);
if (ok) if (ok)
RepInit(G, &I->R); RepInit(G, &I->R);
I->shaderCGO = NULL; I->renderCGO = NULL;
I->primitiveCGO = NULL;
if (cs->Spheroid)
I->spheroidCGO = RepSphereGeneratespheroidCGO(obj, cs, G->Sphere->Sphere[1],
state);
if (ok){ if (ok){
sphere_quality = SettingGet_i(G, cs->Setting, obj->Obj.Setting, cSetting_sph ere_quality);
sphere_mode = SettingGet_i(G, cs->Setting, obj->Obj.Setting, cSetting_sphere _mode); sphere_mode = SettingGet_i(G, cs->Setting, obj->Obj.Setting, cSetting_sphere _mode);
if (!use_shader && (sphere_mode == 5 || sphere_mode == 9)){ if (!use_shader && (sphere_mode == 5 || sphere_mode == 9)){
sphere_mode = 0; sphere_mode = 0;
} }
if(sphere_mode > 0)
sphere_quality = -1;
if(sphere_quality < 0) {
sp = NULL;
} else {
if(draw_quality && (sphere_quality < 3))
sphere_quality = 3;
if(sphere_quality > 4)
sphere_quality = 4;
sp = G->Sphere->Sphere[sphere_quality];
}
} }
if (ok){ if (ok){
sphere_color = sphere_color =
SettingGet_color(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_color); SettingGet_color(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_color);
cartoon_side_chain_helper = cartoon_side_chain_helper =
SettingGet_b(G, cs->Setting, obj->Obj.Setting, cSetting_cartoon_side_chain _helper); SettingGet_b(G, cs->Setting, obj->Obj.Setting, cSetting_cartoon_side_chain _helper);
ribbon_side_chain_helper = ribbon_side_chain_helper =
SettingGet_b(G, cs->Setting, obj->Obj.Setting, cSetting_ribbon_side_chain_ helper); SettingGet_b(G, cs->Setting, obj->Obj.Setting, cSetting_ribbon_side_chain_ helper);
transp = SettingGet_f(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_tran sparency); transp = SettingGet_f(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_tran sparency);
spheroid_scale =
SettingGet_f(G, cs->Setting, obj->Obj.Setting, cSetting_spheroid_scale);
if(sp && spheroid_scale && cs->Spheroid)
spheroidFlag = 1;
else
spheroidFlag = 0;
sphere_scale = SettingGet_f(G, cs->Setting, obj->Obj.Setting, cSetting_spher e_scale); sphere_scale = SettingGet_f(G, cs->Setting, obj->Obj.Setting, cSetting_spher e_scale);
} }
if (ok){ if (ok){
I->R.fRender = (void (*)(struct Rep *, RenderInfo *)) RepSphereRender; I->R.fRender = (void (*)(struct Rep *, RenderInfo *)) RepSphereRender;
I->R.fFree = (void (*)(struct Rep *)) RepSphereFree; I->R.fFree = (void (*)(struct Rep *)) RepSphereFree;
I->R.fSameVis = (int (*)(struct Rep *, struct CoordSet *)) RepSphereSameVis; I->R.fSameVis = (int (*)(struct Rep *, struct CoordSet *)) RepSphereSameVis;
I->LastVertexScale = -1.0F;
I->R.obj = (CObject *) obj; I->R.obj = (CObject *) obj;
I->R.cs = cs; I->R.cs = cs;
I->R.context.object = (void *) obj; I->R.context.object = (void *) obj;
I->R.context.state = state; I->R.context.state = state;
} }
/* raytracing primitives */ /* raytracing primitives */
if (ok)
I->VC = Alloc(float, cs->NIndex * 8);
CHECKOK(ok, I->VC);
if (ok){ if (ok){
I->NC = 0;
map_flag = Calloc(int, cs->NIndex);
}
CHECKOK(ok, map_flag);
if (ok){
I->NT = NULL;
nt = NULL;
v = I->VC;
mf = map_flag;
if(SettingGet_i(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_solvent)) { /* are we generating a solvent surface? */ if(SettingGet_i(G, cs->Setting, obj->Obj.Setting, cSetting_sphere_solvent)) { /* are we generating a solvent surface? */
sphere_add = SettingGet_f(G, cs->Setting, obj->Obj.Setting, cSetting_solve nt_radius); /* if so, get solvent radius */ sphere_add = SettingGet_f(G, cs->Setting, obj->Obj.Setting, cSetting_solve nt_radius); /* if so, get solvent radius */
} }
if(SettingGet_b(G, cs->Setting, obj->Obj.Setting, cSetting_pickable)) { if(SettingGet_b(G, cs->Setting, obj->Obj.Setting, cSetting_pickable)) {
I->R.P = Alloc(Pickable, cs->NIndex + 1); I->R.P = Alloc(Pickable, cs->NIndex + 1);
CHECKOK(ok, I->R.P); CHECKOK(ok, I->R.P);
} }
} }
I->primitiveCGO = CGONew(G);
I->spheroidFlag = spheroidFlag; bool needNormals = (sphere_mode >= 6) && (sphere_mode < 9);
int nspheres = 0;
if (needNormals){
float *v_tmp = VLAlloc(float, 1024);
for(a = 0; ok && a < cs->NIndex; a++) { for(a = 0; ok && a < cs->NIndex; a++) {
a1 = cs->IdxToAtm[a]; a1 = cs->IdxToAtm[a];
ati1 = obj->AtomInfo + a1; ati1 = obj->AtomInfo + a1;
/* store temporary visibility information */ /* store temporary visibility information */
marked[a1] = GET_BIT(ati1->visRep,cRepSphere) && marked[a1] = GET_BIT(ati1->visRep,cRepSphere) &&
RepSphereDetermineAtomVisibility(G, ati1, RepSphereDetermineAtomVisibility(G, ati1,
cartoon_side_chain_helper, ribbon_side_ chain_helper); cartoon_side_chain_helper, ribbon_side_ chain_helper);
if(marked[a1]) { if(marked[a1]) {
RepSphereAddAtomVisInfoToStoredVC(I, obj, cs, state, v, a1, ati1, a, mf, s int cnc = nspheres * 3;
phere_scale, sphere_color, transp, &variable_alpha, sphere_add); nspheres++;
v += 8; VLACheck(v_tmp, float, cnc + 3);
copy3f(cs->Coord + 3 * a, &v_tmp[cnc]);
} }
mf++;
ok &= !G->Interrupt; ok &= !G->Interrupt;
} }
if (ok){ MapType *map = MapNew(G, SPHERE_NORMAL_RANGE, v_tmp, nspheres, NULL);
I->VariableAlphaFlag = variable_alpha; float cut_mult = SphereComputeCutMultiplier(G->Sphere->Sphere[1]);
if(I->NC) float *dot = G->Sphere->Sphere[1]->dot[0];
I->VC = ReallocForSure(I->VC, float, (v - I->VC)); int n_dot = G->Sphere->Sphere[1]->nDot;
else int *active = Alloc(int, 2 * n_dot);
I->VC = ReallocForSure(I->VC, float, 1);
CHECKOK(ok, I->VC);
if(ok && I->R.P) {
I->R.P = Realloc(I->R.P, Pickable, I->NP + 1);
CHECKOK(ok, I->R.P);
if (ok)
I->R.P[0].index = I->NP;
}
}
if (ok){
if(variable_alpha)
I->cullFlag = false;
else {
I->cullFlag = SettingGet_i(G, cs->Setting, obj->Obj.Setting, cSetting_cull
_spheres);
if(I->cullFlag < 0) { /* if negative, then set if more than one state */
I->cullFlag = !(obj->NCSet > 1);
}
}
if(draw_quality)
I->cullFlag = false;
if(spheroidFlag || (!sp))
I->cullFlag = false;
if((I->cullFlag < 2) &&
(SettingGet_f(G, cs->Setting, obj->Obj.Setting, cSetting_sculpting)))
/* optimize build-time performance when sculpting */
I->cullFlag = false;
if((I->cullFlag < 2) && (SettingGetGlobal_f(G, cSetting_roving_spheres) != 0
.0F))
I->cullFlag = false;
if(sp && ((I->cullFlag < 2) ) ) {
/* don't cull unless forced */
I->SSP = sp;
sp = NULL;
}
}
if(!sp) { /* if sp==null, then we're drawing a point-based
sphere rep */
/* sort the vertices by radius */
if(ok && I->NC && I->VC && (!spheroidFlag) && (sphere_mode != 1)) {
int *ix = NULL;
float *vc_tmp = NULL;
Pickable *pk_tmp = NULL;
int a;
ix = Alloc(int, I->NC);
CHECKOK(ok, ix);
if (ok)
vc_tmp = Alloc(float, I->NC * 8);
CHECKOK(ok, vc_tmp);
if (ok)
pk_tmp = Alloc(Pickable, I->NP + 1);
CHECKOK(ok, pk_tmp);
if(ok && vc_tmp && pk_tmp && ix) {
UtilCopyMem(vc_tmp, I->VC, sizeof(float) * 8 * I->NC);
if (I->R.P)
UtilCopyMem(pk_tmp, I->R.P, sizeof(Pickable) * (I->NP + 1));
UtilSortIndex(I->NC, I->VC, ix, (UtilOrderFn *) RadiusOrder);
if (I->R.P)
UtilCopyMem(I->R.P, pk_tmp, sizeof(Pickable));
for(a = 0; a < I->NC; a++) {
UtilCopyMem(I->VC + (a * 8), vc_tmp + (8 * ix[a]), sizeof(float) * 8);
if (I->R.P)
UtilCopyMem(I->R.P + (a + 1), pk_tmp + ix[a] + 1, sizeof(Pickable));
}
}
FreeP(vc_tmp);
FreeP(ix);
FreeP(pk_tmp);
}
if(ok && (sphere_mode >= 6) && (sphere_mode < 9) && I->NC) {
/* compute sphere normals in VN to approximate a surface */
ok = RepSphereComputeSphereNormals(I);
}
I->cullFlag = false;
I->V = NULL;
I->NT = NULL;
I->N = 0;
I->SP = NULL;
} else {
/* if sp, drawing geometry-based sphere rep */
if(I->cullFlag && sp) {
if (ok)
I->V = Alloc(float, I->NC * (sp->NVertTot * 31)); /* double check 31 *
/
CHECKOK(ok, I->V);
if (ok)
I->NT = Alloc(int, cs->NIndex);
CHECKOK(ok, I->NT);
if (ok)
visFlag = Alloc(int, sp->nDot);
CHECKOK(ok, visFlag);
/* hmm...need to compute max(sphere_scale) for all atoms... */
if (ok)
map =
MapNewFlagged(G, MAX_VDW * sphere_scale + sphere_add, cs->Coord, cs->NI
ndex, NULL,
map_flag);
CHECKOK(ok, map);
if (ok)
ok &= MapSetupExpress(map);
} else if (ok){
if(sp)
I->V = Alloc(float, I->NC * (4 + sp->NVertTot * 6));
else
I->V = Alloc(float, I->NC * 7); /* one color, one alpha, one vertex p
er spheres */
CHECKOK(ok, I->V);
}
/* rendering primitives */
I->N = 0;
I->SP = sp;
v = I->V;
nt = I->NT;
ok &= MapSetupExpress(map);
for(a = 0; ok && a < cs->NIndex; a++) { for(a = 0; ok && a < cs->NIndex; a++) {
a1 = cs->IdxToAtm[a]; a1 = cs->IdxToAtm[a];
if(marked[a1]) {
ati1 = obj->AtomInfo + a1; ati1 = obj->AtomInfo + a1;
vis_flag = marked[a1]; RepSphereSetNormalForSphere(I, map, v_tmp, &v_tmp[a * 3], cut_mult, a, a
ctive, dot, n_dot);
/* don't show backbone atoms if side_chain_helper is on */ RepSphereAddAtomVisInfoToStoredVC(I, obj, cs, state, a1, ati1, a, sphere
_scale, sphere_color, transp, &variable_alpha, sphere_add);
if(vis_flag) { }
ok &= RepSphereGenerateGeometryForSphere(I, obj, cs, state, a1, ati1, a,
sphere_scale, sphere_color, spheroid_scale, transp, &variable_alpha, sphere_add,
spheroidFlag, sp, visFlag, marked, map, nt, &v);
if(nt)
nt++;
ok &= !G->Interrupt; ok &= !G->Interrupt;
if (!ok)
break;
} }
FreeP(active);
VLAFreeP(v_tmp);
MapFree(map);
} else { // no normals necessary
for(a = 0; ok && a < cs->NIndex; a++) {
a1 = cs->IdxToAtm[a];
ati1 = obj->AtomInfo + a1;
/* store temporary visibility information */
marked[a1] = GET_BIT(ati1->visRep,cRepSphere) &&
RepSphereDetermineAtomVisibility(G, ati1,
cartoon_side_chain_helper, ribbon_side_
chain_helper);
if(marked[a1]) {
nspheres++;
RepSphereAddAtomVisInfoToStoredVC(I, obj, cs, state, a1, ati1, a, sphere
_scale, sphere_color, transp, &variable_alpha, sphere_add);
}
ok &= !G->Interrupt;
} }
} }
CGOStop(I->primitiveCGO);
if(ok) { if(ok) {
if(!I->LastVisib) if(!I->LastVisib)
I->LastVisib = Alloc(int, cs->NIndex); I->LastVisib = Alloc(bool, cs->NIndex);
CHECKOK(ok, I->LastVisib); CHECKOK(ok, I->LastVisib);
if(ok && !I->LastColor) if(ok && !I->LastColor)
I->LastColor = Alloc(int, cs->NIndex); I->LastColor = Alloc(int, cs->NIndex);
CHECKOK(ok, I->LastColor); CHECKOK(ok, I->LastColor);
if (ok){ if (ok){
lv = I->LastVisib; lv = I->LastVisib;
lc = I->LastColor; lc = I->LastColor;
obj = cs->Obj; obj = cs->Obj;
ai2 = obj->AtomInfo; AtomInfoType *ai2 = obj->AtomInfo;
if(sphere_color == -1){ if(sphere_color == -1){
for(a = 0; a < cs->NIndex; a++) { for(a = 0; a < cs->NIndex; a++) {
int at = cs->IdxToAtm[a]; int at = cs->IdxToAtm[a];
*(lv++) = marked[at]; *(lv++) = marked[at];
*(lc++) = (ai2 + at)->color; *(lc++) = (ai2 + at)->color;
} }
} else { } else {
for(a = 0; a < cs->NIndex; a++) { for(a = 0; a < cs->NIndex; a++) {
*(lv++) = marked[cs->IdxToAtm[a]]; *(lv++) = marked[cs->IdxToAtm[a]];
*(lc++) = sphere_color; *(lc++) = sphere_color;
} }
} }
} }
} }
if(ok && I->V) {
if(I->N) {
I->V = ReallocForSure(I->V, float, (v - I->V));
CHECKOK(ok, I->V);
if(ok && I->NT){
I->NT = ReallocForSure(I->NT, int, (nt - I->NT));
CHECKOK(ok, I->NT);
}
} else {
I->V = ReallocForSure(I->V, float, 1);
CHECKOK(ok, I->V);
if(ok && I->NT){
I->NT = ReallocForSure(I->NT, int, 1);
CHECKOK(ok, I->NT);
}
}
}
FreeP(marked); FreeP(marked);
FreeP(visFlag); if(nspheres == 0 || !ok) {
FreeP(map_flag);
if(map)
MapFree(map);
if(!ok) {
RepSphereFree(I); RepSphereFree(I);
I = NULL; I = NULL;
} }
return (Rep *) I; return (Rep *) I;
} }
 End of changes. 86 change blocks. 
1847 lines changed or deleted 297 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)