"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "layer2/RepLabel.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.

RepLabel.cpp  (pymol-v2.1.0.tar.bz2):RepLabel.cpp  (pymol-open-source-2.2.0)
skipping to change at line 36 skipping to change at line 36
#include"Color.h" #include"Color.h"
#include"Map.h" #include"Map.h"
#include"Setting.h" #include"Setting.h"
#include"main.h" #include"main.h"
#include"Scene.h" #include"Scene.h"
#include"Text.h" #include"Text.h"
#include"Matrix.h" #include"Matrix.h"
#include"ShaderMgr.h" #include"ShaderMgr.h"
#include"CGO.h" #include"CGO.h"
/*
* Memory layout of the RepLabel::V array
*/
struct VItemType {
float color[3]; // 0- 2: label_color
float coord[3]; // 3- 5: atom coordinate
float screen_point[3]; // 6- 8: coordinate + label_placement_offset or lab
el_screen_point
float connector_color[3]; // 9-11: label_connector_color
float position[3]; // 12-14: label_position
float relativeMode_f; // 15: bitmask
// = (drawConnector << 0)
// | (isScreenCoord << 1)
// | (isPixelCoord << 2)
// | (at_label_z_target << 3)
float spacing; // 16: label_multiline_spacing
float justification; // 17: label_multiline_justification
float padding[3]; // 18-20: label_padding
float draw_var_f; // 21: bitmask
// (1 << 0) * label_connector +
// (1 << 1) * label_bg +
// (1 << 2) * label_bg_outline +
// (1 << 3) * label_connector_mode_1 +
// (1 << 4) * label_connector_mode_2 +
// (1 << 5) * label_connector_mode_3 +
// (1 << 6) * label_connector_mode_4 +
// (1 << 7) * ray_label_connector_flat
float bg_alpha; // 22: 1.0 - label_bg_transparency
float bg_color[3]; // 23-25: label_bg_color
float connector_width; // 26: label_connector_width
float connector_ext_len; // 27: label_connector_ext_length
};
typedef struct RepLabel { typedef struct RepLabel {
Rep R; Rep R;
// VItemType *V;
float *V; float *V;
int *L; int *L;
int N; int N;
int OutlineColor; int OutlineColor;
CGO *shaderCGO; CGO *shaderCGO;
int texture_font_size;
} RepLabel; } RepLabel;
#define SHADERCGO I->shaderCGO #define SHADERCGO I->shaderCGO
#include"ObjectMolecule.h" #include"ObjectMolecule.h"
void RepLabelFree(RepLabel * I); void RepLabelFree(RepLabel * I);
static void RepLabelInit(RepLabel *I) static void RepLabelInit(RepLabel *I)
{ {
I->shaderCGO = NULL; I->shaderCGO = NULL;
I->texture_font_size = 0;
} }
void RepLabelFree(RepLabel * I) void RepLabelFree(RepLabel * I)
{ {
FreeP(I->R.P); RepPurge(&I->R);
FreeP(I->V); FreeP(I->V);
FreeP(I->L); FreeP(I->L);
if (I->shaderCGO){ if (I->shaderCGO){
CGOFree(I->shaderCGO); CGOFree(I->shaderCGO);
} }
OOFreeP(I); OOFreeP(I);
} }
#define MAX_LABEL_TEXTURE_SIZE 256
#define MAX_LABEL_FOR_ALWAYS_REFRESH 32
#define PERCENTAGE_CHANGE_FOR_REFRESH .2f
short InvalidateShaderCGOIfTextureNeedsUpdate(PyMOLGlobals *G, float font_size,
int texture_font_size, int *sizeArg){
float v_scale, perc = 0.f;
int size, diff;
short inv = false;
v_scale = SceneGetScreenVertexScale(G, NULL);
size = (int) (0.5F - font_size / v_scale);
if (size <= 0)
size = 1;
if (size > MAX_LABEL_TEXTURE_SIZE){ // if label size is above max, just set t
o max size
size = MAX_LABEL_TEXTURE_SIZE;
if (texture_font_size!=size)
inv = true;
} else {
if (font_size > 0 || size < MAX_LABEL_FOR_ALWAYS_REFRESH){
// if less than min, always refresh labels on texture if size changes
if (texture_font_size!=size)
inv = true;
} else {
// label is larger than min, but changes more than a percentage, refresh o
n texture
diff = size - texture_font_size;
diff = diff < 0 ? -diff : diff;
perc = (diff / (float)size);
inv = (perc > PERCENTAGE_CHANGE_FOR_REFRESH);
}
}
*sizeArg = size;
return (inv || !texture_font_size);
}
static float CLAMP_VALUE(float val, float min, float max){
return ( val < min ? min : ( val > max ? max : val) );
}
static void RepLabelAdjustScreenZ(PyMOLGlobals *G, float *pt){
short outside;
outside = (pt[2] < -1.f || pt[2] > 1.f);
if (!outside){
pt[2] = CLAMP_VALUE(pt[2], -.9999, .97); // .98 b/c resolution in the back i
s lower
}
}
static void addXYtoVertex(float x, float y, float *xv, float *yv, float *origv,
float *v){
float tmp3f[3];
copy3f(origv, v);
mult3f(xv, x, tmp3f);
add3f(v, tmp3f, v);
mult3f(yv, y, tmp3f);
add3f(v, tmp3f, v);
}
static void addXYZtoVertex(float x, float y, float z, float *xv, float *yv,
float *zv, float *origv, float *v)
{
float tmp3f[3];
copy3f(origv, v);
mult3f(xv, x, tmp3f);
add3f(v, tmp3f, v);
mult3f(yv, y, tmp3f);
add3f(v, tmp3f, v);
mult3f(zv, z, tmp3f);
add3f(v, tmp3f, v);
}
static void RayDrawLineAsGeometryWithOffsets(CRay *ray, float *pt1, float *pt2,
float *spt1, float *spt2, float *xn, float *yn, float *zn, float line_width,
float topext, float bottomext, float *color, float *dirv,
unsigned char noLighting)
{
float pts[4][3];
float pt1E[3], pt2E[3];
float tmpV[3], tmpV2[3], linev[3];
float nzn[3] = { 0.f, 0.f, 1.f };
copy3f(pt1, pt1E);
copy3f(pt2, pt2E);
subtract3f(spt1, spt2, tmpV);
copy3f(tmpV, linev);
normalize3f(linev);
mult3f(linev, line_width, linev);
cross_product3f(tmpV, nzn, tmpV2);
normalize3f(tmpV2);
mult3f(tmpV2, line_width, dirv);
addXYtoVertex(dirv[0], dirv[1], xn, yn, pt1, pt1E);
addXYtoVertex(topext * linev[0], topext * linev[1], xn, yn, pt1E, pts[0]);
addXYtoVertex(dirv[0], dirv[1], xn, yn, pt2, pt2E);
addXYtoVertex(-topext * linev[0], -topext * linev[1], xn, yn, pt2E, pts[1]);
addXYtoVertex(-dirv[0], -dirv[1], xn, yn, pt1, pt1E);
addXYtoVertex(bottomext * linev[0], bottomext * linev[1], xn, yn, pt1E, pts[2]
);
addXYtoVertex(-dirv[0], -dirv[1], xn, yn, pt2, pt2E);
addXYtoVertex(-bottomext * linev[0], -bottomext * linev[1], xn, yn, pt2E, pts[
3]);
ray->triangle3fv(pts[0], pts[1], pts[2], zn, zn, zn, color, color, color);
ray->setLastToNoLighting(noLighting);
ray->triangle3fv(pts[1], pts[2], pts[3], zn, zn, zn, color, color, color);
ray->setLastToNoLighting(noLighting);
}
#ifndef PURE_OPENGL_ES_2
void drawLine2DCross(float cw, float x1, float y1, float x2, float y2, float *cr
oss){
float lvect[3];
float nzn[3] = { 0.f, 0.f, 1.f };
lvect[0] = x2 - x1;
lvect[1] = y2 - y1;
normalize2f(lvect);
cross_product3f(lvect, nzn, cross);
mult3f(cross, cw, cross);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(x1 + cross[0], y1 + cross[1], 0.f);
glVertex3f(x2 + cross[0], y2 + cross[1], 0.f);
glVertex3f(x1 - cross[0], y1 - cross[1], 0.f);
glVertex3f(x2 - cross[0], y2 - cross[1], 0.f);
glEnd();
}
void drawLine2D(float cw, float x1, float y1, float x2, float y2){
float cross[3];
drawLine2DCross(cw, x1, y1, x2, y2, cross);
}
/* Draw Line/Polygon from point (x1,y1) to (x2,y2) with different Z's, where the
current Z is
at world point curpt with the line starting at (x1,y1), and the second point
(x2,y2) is
at the world point pt (i.e., the offset is embedded into the matrix convMatri
x computed from
SceneGenerateMatrixToAnotherZFromZ */
void drawLineToPointInWorldCross(PyMOLGlobals *G, float cw, float x1, float y1,
float x2, float y2, float *cross, float *pt, float *curpt){
float lvect[3];
float nzn[3] = { 0.f, 0.f, 1.f };
float convMatrix[16];
float tmppt[3];
SceneGenerateMatrixToAnotherZFromZ(G, convMatrix, curpt, pt);
lvect[0] = x2 - x1;
lvect[1] = y2 - y1;
normalize2f(lvect);
cross_product3f(lvect, nzn, cross);
mult3f(cross, cw, cross);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(x1 + cross[0], y1 + cross[1], 0.f);
// target point 1 in pt screen coordinates
tmppt[0] = cross[0]; tmppt[1] = cross[1]; tmppt[2] = 0.f;
MatrixTransformC44f3f(convMatrix, tmppt, tmppt);
glVertex3fv(tmppt);
glVertex3f(x1 - cross[0], y1 - cross[1], 0.f);
// target point 2 in pt screen coordinates
tmppt[0] = -cross[0]; tmppt[1] = -cross[1]; tmppt[2] = 0.f;
MatrixTransformC44f3f(convMatrix, tmppt, tmppt);
glVertex3fv(tmppt);
glEnd();
}
#define CLIP_LEFT 1
#define CLIP_RIGHT 2
#define CLIP_TOP 4
#define CLIP_BOTTOM 8
short CLIPt(float denom, float num, float *tE, float *tL, short *clipedges, shor
t bitmask){
float t;
if (denom > 0){
t = num / denom;
if (t > *tL)
return 0;
else if (t > *tE){
*tE = t;
*clipedges = bitmask;
}
} else if (denom < 0){
t = num / denom;
if (t < *tE)
return 0;
else if (t < *tL){
*tL = t;
*clipedges = bitmask;
}
} else if (num > 0)
return 0;
return 1;
}
/* This function clips the line inside of the (-xmax,-ymax, xmax, ymax) rectangl
e */
void Clip2D(float xmax, float ymax, float *x0, float *y0, float *x1, float *y1,
short *visible, short *clipedges){
float dx = *x1 - *x0;
float dy = *y1 - *y0;
*visible = 0;
*clipedges = 0;
if (dx == 0.f && dy == 0.f && fabs(*x0) < xmax && fabs(*y0) < ymax)
*visible = 1;
else {
float tE = 0.f, tL = 1.f;
if (CLIPt(dx, -xmax - *x0, &tE, &tL, clipedges, CLIP_LEFT)) // left
if (CLIPt(-dx, *x0 - xmax, &tE, &tL, clipedges, CLIP_RIGHT)) // right
if (CLIPt(dy, -ymax - *y0, &tE, &tL, clipedges, CLIP_BOTTOM)) // bottom
if (CLIPt(-dy, *y0 - ymax, &tE, &tL, clipedges, CLIP_TOP)){ // top
if (*clipedges){
*visible = 1;
if (tL < 1.f){
*x1 = *x0 + tL * dx;
*y1 = *y0 + tL * dy;
}
if (tE > 0.f){
*x0 =+ tE * dx;
*y0 += tE * dy;
}
}
}
}
}
void Clip2DLine(float xmax, float ymax, float *line, short *visible, short *clip
edges){
Clip2D(xmax, ymax, &line[0], &line[1], &line[2], &line[3], visible, clipedges)
;
}
void glVertex3fTransformed(float *convMatrix, float x, float y, float z){
float tmppt[3] = { x, y, z };
MatrixTransformC44f3f(convMatrix, tmppt, tmppt);
glVertex3fv(tmppt);
}
void drawLineToPointInWorldCrossClip(PyMOLGlobals *G, int label_z_target, float
cw, float x1, float y1, float x2, float y2, float *cross, float *pt, float *curp
t, float cx, float cy){
float lvect[3];
float nzn[3] = { 0.f, 0.f, 1.f };
float convMatrix[16];
short visible1, edges1, visible2, edges2;
float line1[4], line2[4];
if (!label_z_target){
SceneGenerateMatrixToAnotherZFromZ(G, convMatrix, curpt, pt);
} else {
// set convMatrix to translation from label center to target center, i.e., (
x2, y2)
identity44f(convMatrix);
MatrixTranslateC44f(convMatrix, x2, y2, 0.f);
}
lvect[0] = x2 - x1;
lvect[1] = y2 - y1;
normalize2f(lvect);
cross_product3f(lvect, nzn, cross);
mult3f(cross, cw, cross);
line1[0] = x1 + cross[0]; line1[1] = y1 + cross[1];
line1[2] = x2 + cross[0]; line1[3] = y2 + cross[1];
line2[0] = x1 - cross[0]; line2[1] = y1 - cross[1];
line2[2] = x2 - cross[0]; line2[3] = y2 - cross[1];
Clip2DLine(cx, cy, line1, &visible1, &edges1);
Clip2DLine(cx, cy, line2, &visible2, &edges2);
if (visible1 && visible2){
if (edges1 == edges2){
// if both lines intersect the same edge, just draw the quad
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(line1[2], line1[3], 0.f);
glVertex3fTransformed(convMatrix, cross[0], cross[1], 0.f);
glVertex3f(line2[2], line2[3], 0.f);
glVertex3fTransformed(convMatrix, - cross[0], - cross[1], 0.f);
glEnd();
} else {
// if both lines intersect different edges, need to add the corner
// and generate correct order
float corner[2];
short edges = edges1 | edges2;
corner[0] = (edges & CLIP_LEFT) ? -cx : cx;
corner[1] = (edges & CLIP_BOTTOM) ? -cy : cy;
// staggered triangles which include the corner
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(line1[2], line1[3], 0.f);
glVertex3fTransformed(convMatrix, cross[0], cross[1], 0.f);
glVertex3f(corner[0], corner[1], 0.f);
glVertex3fTransformed(convMatrix, - cross[0], - cross[1], 0.f);
glVertex3f(line2[2], line2[3], 0.f);
glEnd();
}
}
}
void drawLineToPointInWorld(PyMOLGlobals *G, float cw, float x1, float y1, float
x2, float y2, float *pt, float *curpt){
float cross[3];
drawLineToPointInWorldCross(G, cw, x1, y1, x2, y2, cross, pt, curpt);
}
void drawLine2DCheckZTargetCross(PyMOLGlobals *G, short label_z_target, float *p
t, float *curpt, float cw, float x1, float y1, float x2, float y2, float *cross)
{
if (label_z_target){
drawLine2DCross(cw, x1, y1, x2, y2, cross);
} else {
drawLineToPointInWorldCross(G, cw, x1, y1, x2, y2, cross, pt, curpt);
}
}
void drawLine2DCheckZTarget(PyMOLGlobals *G, short label_z_target, float *pt, fl
oat *curpt, float cw, float x1, float y1, float x2, float y2){
float cross[3];
drawLine2DCheckZTargetCross(G, label_z_target, pt, curpt, cw, x1, y1, x2, y2,
cross);
}
void drawLine2DCheckZTargetClip(PyMOLGlobals *G, short label_z_target, float *pt
, float *curpt, float cw, float x1, float y1, float x2, float y2, float cx, floa
t cy){
float cross[3];
drawLineToPointInWorldCrossClip(G, label_z_target, cw, x1, y1, x2, y2, cross,
pt, curpt, cx, cy);
}
void drawLineAsGeometryWithOffsets(float *pt1, float *pt2, float *spt1, float *s
pt2, float *xn, float *yn, float *zn, float line_width, float topext, float bott
omext, float *dirv){
float pt1E[3], pt2E[3];
float tmpV[3], tmpV2[3], linev[3];
float nzn[3] = { 0.f, 0.f, 1.f };
copy3f(pt1, pt1E);
copy3f(pt2, pt2E);
subtract3f(spt1, spt2, tmpV);
copy3f(tmpV, linev);
normalize3f(linev);
mult3f(linev, line_width, linev);
glBegin(GL_TRIANGLE_STRIP);
cross_product3f(tmpV, nzn, tmpV2);
normalize3f(tmpV2);
mult3f(tmpV2, line_width, dirv);
addXYtoVertex(dirv[0], dirv[1], xn, yn, pt1, pt1E);
addXYtoVertex(topext * linev[0], topext * linev[1], xn, yn, pt1E, pt1E);
glVertex3fv(pt1E);
addXYtoVertex(dirv[0], dirv[1], xn, yn, pt2, pt2E);
addXYtoVertex(-topext * linev[0], -topext * linev[1], xn, yn, pt2E, pt2E);
glVertex3fv(pt2E);
addXYtoVertex(-dirv[0], -dirv[1], xn, yn, pt1, pt1E);
addXYtoVertex(bottomext * linev[0], bottomext * linev[1], xn, yn, pt1E, pt1E);
glVertex3fv(pt1E);
addXYtoVertex(-dirv[0], -dirv[1], xn, yn, pt2, pt2E);
addXYtoVertex(-bottomext * linev[0], -bottomext * linev[1], xn, yn, pt2E, pt2E
);
glVertex3fv(pt2E);
glEnd();
}
void RepLabelRenderBackgroundInImmediate(PyMOLGlobals *G, RepLabel *I, float *v,
int draw_var, float *tCenterPt, short relativeMode, float *xn, float *yn,
float *PmvMatrix, float *RotMatrix, int
screenwidth, int screenheight, float *screenWorldOffset, float *indentFactor,
float text_width, float text_height, flo
at font_size){
float pos[3], *labelpos = TextGetLabelPushPos(G);
float hwidth = text_width / 2.f, hheight = text_height / 2.f;
short label_connector_mode = (draw_var & 8) ? 1 : (draw_var & 16) ? 2 : (draw_
var & 32) ? 3 : (draw_var & 64) ? 4 : 0;
float cw = *(v + 26) / 2.f;
short label_z_target = relativeMode & 8;
float indentFactorT[2] = { indentFactor[0]*text_width/2.f, indentFactor[1]*tex
t_height/2.f };
{// taking into account screen adjustments : indent and screen world offset to
the label point
float v_scale, xn[3], yn[3];
v_scale = SceneGetScreenVertexScale(G, NULL);
SceneGetScaledAxesAtPoint(G, labelpos, xn, yn);
addXYtoVertex(indentFactorT[0] + screenWorldOffset[0]/v_scale, indentFactorT
[1] + screenWorldOffset[1]/v_scale, xn, yn, labelpos, pos);
}
{
float tCenter[4], tTarget[4], tVec[3];
float doNotDraw;
short drawLine = true;
float dVectorInPixels[2], dVector[2];
float v_scale;
short visible;
v_scale = SceneGetScreenVertexScale(G, NULL);
copy3f(v+6, tCenter);
tCenter[3] = 1.f;
copy3f(v+3, tTarget);
tTarget[3] = 1.f;
MatrixTransformC44f4f(PmvMatrix, tTarget, tTarget);
normalize4f(tTarget);
if (!((relativeMode & 2) || (relativeMode & 4))){ // label_relative_mode = 0
, not 1 or 2
MatrixTransformC44f4f(PmvMatrix, tCenter, tCenter);
normalize4f(tCenter);
} // label_relative_mode =1 : nothing, lready in screen coordinates
if (relativeMode & 4){ // label_relative_mode = 2
tCenter[0] = (tCenter[0] / screenwidth) * 2 - 1.f;
tCenter[1] = (tCenter[1] / screenheight) * 2 - 1.f;
}
subtract3f(tTarget, tCenter, tVec);
dVectorInPixels[0] = .5f * (screenwidth * tVec[0]) - (screenWorldOffset[0]/v
_scale) - indentFactorT[0];
dVectorInPixels[1] = .5f * (screenheight * tVec[1]) - (screenWorldOffset[1]/
v_scale) - indentFactorT[1];
dVector[0] = (dVectorInPixels[0] / text_width);
dVector[1] = (dVectorInPixels[1] / text_height);
doNotDraw = ((fabs(dVector[0])) <= .5f && (fabs(dVector[1])) <= .5f) ? 1.f :
0.f;
if (!(draw_var & 1) || doNotDraw > .5f)
drawLine = false;
if (label_z_target){
visible = SceneGetVisible(G, v+3);
ScenePushRasterMatrix(G, v + 3);
glTranslatef(-dVectorInPixels[0], -dVectorInPixels[1], 0.f);
} else {
visible = SceneGetVisible(G, pos);
ScenePushRasterMatrix(G, pos);
}
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.f, 1.f);
if (!visible){
draw_var = 0;
drawLine = 0;
}
if (draw_var & 6){ // draw background or background outline
if (draw_var & 2){ // draw background
float bgwidth = hwidth, bgheight = hheight;
if (draw_var & 4){
bgwidth -= cw;
bgheight -= cw;
}
glColor4f(v[23], v[24], v[25], v[22]);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(bgwidth, bgheight, 0.f);
glVertex3f(bgwidth, -bgheight, 0.f);
glVertex3f(-bgwidth, bgheight, 0.f);
glVertex3f(-bgwidth, -bgheight, 0.f);
glEnd();
}
if (draw_var & 4){ // draw background outline
glColor4f(v[9], v[10], v[11], 1.f);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(-hwidth - cw, -hheight - cw, 0.f); // 1
glVertex3f(-hwidth - cw, hheight + cw, 0.f); // 2 2---------------4
glVertex3f(-hwidth + cw, hheight - cw, 0.f); // 3 |\ / |
glVertex3f(hwidth + cw, hheight + cw, 0.f); // 4 | 3----------5 |
glVertex3f(hwidth - cw, hheight - cw, 0.f); // 5 | | | |
glVertex3f(hwidth + cw, -hheight - cw, 0.f); // 6 | 9----------7 |
glVertex3f(hwidth - cw, -hheight + cw, 0.f); // 7 |/ \ |
glVertex3f(-hwidth - cw, -hheight - cw, 0.f); // 8 1/8---------------6
glVertex3f(-hwidth + cw, -hheight + cw, 0.f); // 9
glVertex3f(-hwidth + cw, hheight - cw, 0.f); // 3
glEnd();
}
}
if (drawLine){
float xoff, yoff;
glColor4f(v[9], v[10], v[11], 1.f);
switch (label_connector_mode){
case 0:
{
float hmid = (fabs(dVector[0]) >= .5) ? 0.f : 1.f;
float vmid = (fabs(dVector[1]) >= .5) ? 0.f : 1.f;
float right = (1.f - hmid) * ((dVector[0] > 0.f) ? 1.f : 0.f) + hmid *
.5f;
float top = (1.f - vmid) * ((dVector[1] > 0.f) ? 1.f : 0.f) + vmid * .5
f;
float labx, laby;
xoff = 2.f * (right - .5);
yoff = 2.f * (top - .5);
labx = xoff * hwidth;
laby = yoff * hheight;
drawLine2DCheckZTarget(G, label_z_target, v + 3, pos, cw, labx, laby, d
VectorInPixels[0], dVectorInPixels[1]);
}
break;
case 3:
{
float hmid = (fabs(dVector[0]) >= .5f) ? 0.f : 1.f;
float vmid = (fabs(dVector[1]) >= .5f) ? 0.f : 1.f;
float right = (1.f - hmid) * ((dVector[0] > 0.f) ? 1.f : 0.f) + hmid *
(.5f + dVector[0]);
float top = (1.f - vmid) * ((dVector[1] > 0.f) ? 1.f : 0.f) + vmid * (.
5f + dVector[1]);
float labx, laby;
xoff = 2.f * (right - .5);
yoff = 2.f * (top - .5);
labx = xoff * hwidth;
laby = yoff * hheight;
drawLine2DCheckZTarget(G, label_z_target, v + 3, pos, cw, labx, laby, d
VectorInPixels[0], dVectorInPixels[1]);
}
break;
case 1:
{
float drawVectorN[2], absyx, notabsyx, dvxy, dvyx, hdir, vdir;
float labx, laby;
copy2f(dVector, drawVectorN);
normalize2f(drawVectorN);
absyx = fabs(drawVectorN[0]) >= fabs(drawVectorN[1]) ? 1.f : 0.f;
notabsyx = 1.f - absyx;
hdir = 2.f * ( ( (drawVectorN[0] > 0.f) ? 1.f : 0.f ) - .5f);
vdir = 2.f * ( ( (drawVectorN[1] > 0.f) ? 1.f : 0.f ) - .5f);
dvxy = dVector[0] / dVector[1];
dvyx = dVector[1] / dVector[0];
xoff = (absyx * hdir) + (notabsyx * vdir * dvxy);
yoff = (notabsyx * vdir) + (absyx * hdir * dvyx);
labx = xoff * hwidth;
laby = yoff * hheight;
if ((draw_var & 6) == 2){
// if ONLY background is drawn in connector_mode 1, then the line
// needs to be clipped so that it is flush to the background
drawLine2DCheckZTargetClip(G, label_z_target, v + 3, pos, cw, 0, 0, d
VectorInPixels[0], dVectorInPixels[1], hwidth, hheight);
} else {
drawLine2DCheckZTarget(G, label_z_target, v + 3, pos, cw, labx, laby,
dVectorInPixels[0], dVectorInPixels[1]);
}
}
break;
case 2:
case 4:
{
float extLength, rightorig, right, top, xofforig;
short label_connector_mode_4 = (label_connector_mode == 4);
short hmid = 0, vmid = 0;
float labx, laby, extx, exty;
if (label_connector_mode_4){
hmid = (fabs(dVector[0]) < .5f);
vmid = (fabs(dVector[1]) < .5f);
}
if (font_size < 0.f){
extLength = - (*(v + 27) * font_size / text_height) / v_scale;
} else {
extLength = *(v + 27) * font_size / text_height;
}
if (hmid){
rightorig = (.5f + dVector[0]);
right = rightorig;
} else {
rightorig = dVector[0] >= 0.f ? 1.f : 0.f;
right = rightorig + (rightorig - .5f) * CLAMP_VALUE(fabs(2.f * dVecto
r[0])-1.f, 0.f, 2.f * extLength * fabs(text_height/(float)text_width));
}
if (vmid){
top = (.5f + dVector[1]);
} else {
top = (dVector[1] >= 0.f) ? 1.f : 0.f;
}
xofforig = 2. * (rightorig - .5);
xoff = 2.f * (right - .5);
yoff = 2.f * (top - .5);
labx = xofforig * hwidth;
laby = yoff * hheight;
extx = xoff * hwidth;
exty = yoff * hheight;
{ // drawing the triangle filler between the two lines (connector_mode
2 or 4)
float dirv1[3], dirv2[3], cross[3];
drawLine2DCheckZTargetCross(G, label_z_target, v + 3, pos, cw, extx,
exty, dVectorInPixels[0], dVectorInPixels[1], dirv1);
drawLine2DCross(cw, extx, exty, labx, laby, dirv2);
dirv1[0] = -dirv1[0]; dirv1[1] = -dirv1[1]; // switch normal b/c dr
awLine2DCheckZTargetCross call above has target as second
dirv1[2] = dirv2[2] = 0.f;
cross_product3f(dirv1, dirv2, cross);
glBegin(GL_TRIANGLES);
glVertex3f(extx, exty, 0.f);
if (cross[2] < 0.f){
glVertex3f(extx - dirv1[0], exty - dirv1[1], 0.f);
glVertex3f(extx - dirv2[0], exty - dirv2[1], 0.f);
} else {
glVertex3f(extx + dirv2[0], exty + dirv2[1], 0.f);
glVertex3f(extx + dirv1[0], exty + dirv1[1], 0.f);
}
glEnd();
}
}
break;
}
}
}
glDisable(GL_POLYGON_OFFSET_FILL);
ScenePopRasterMatrix(G);
}
#endif
static int lineSegIntersection(float *p1, float *p2, float *p3, float *p4, float
*po) {
float distAB, theCos, theSin, newX, abpos;
float p2i[2], p3i[2], p4i[2];
if ((p1[0]==p2[0] && p1[1]==p2[1]) || (p3[0]==p4[0] && p3[1]==p4[1])) ret
urn 0;
if ((p1[0]==p3[0] && p1[1]==p3[1]) || (p2[0]==p3[0] && p2[1]==p3[1])
|| (p1[0]==p4[0] && p1[1]==p4[1]) || (p2[0]==p4[0] && p2[1]==p4[1])) {
return 0; }
p2i[0] = p2[0]; p2i[1] = p2[1];
p3i[0] = p3[0]; p3i[1] = p3[1];
p4i[0] = p4[0]; p4i[1] = p4[1];
p2i[0] -= p1[0]; p2i[1] -= p1[1];
p3i[0] -= p1[0]; p3i[1] -= p1[1];
p4i[0] -= p1[0]; p4i[1] -= p1[1];
distAB = sqrt(p2i[0] * p2i[0] + p2i[1] * p2i[1]);
theCos = p2i[0] / distAB;
theSin = p2i[1] / distAB;
newX = p3i[0] * theCos + p3i[1] * theSin;
p3i[1] = p3i[1] * theCos - p3i[0] * theSin;
p3i[0] = newX;
newX = p4i[0] * theCos + p4i[1] * theSin;
p4i[1] = p4i[1] * theCos - p4i[0] * theSin;
p4i[0] = newX;
if ((p3i[1] < 0. && p4i[1]<0.) || (p3i[1] >= 0. && p4i[1] >= 0.)) return
0;
abpos = p4i[0] + (p3i[0] - p4i[0]) * p4i[1] / (p4i[1] - p3i[1]);
if (abpos<0. || abpos>distAB) return 0;
po[0] = p1[0] + abpos * theCos;
po[1] = p1[1] + abpos * theSin;
return 1;
}
typedef struct lineSeg_s {
float p1[2];
float p2[2];
} lineSeg_t;
static void RepLabelRenderRayBackground(RepLabel * I, RenderInfo * info, float *
v, int draw_var){
CRay *ray = info->ray;
PyMOLGlobals *G = I->R.G;
float *screenWorldOffset = TextGetScreenWorldOffset(G);
float text_width = TextGetWidth(G), text_height = TextGetHeight(G);
float *indentFactor = TextGetIndentFactor(G);
float endpointOnBBX[3], tmp3f[3];
float torigCenter[3], tTarget[4], tVec[3], dVectorInPixels[2], dVector[2];
float xoff = 0.f, yoff = 0.f;
float doNotDraw;
float v_scale;
short drawLine = true;
float xn[3], yn[3], zn[3];
float connector_width = *(v + 26);
float *RotMatrix = ray->Rotation;
lineSeg_t labelTop, labelBottom, labelLeft, labelRight;
short label_con_flat = 128 & (int)*(v + 21);
short label_connector_mode = (draw_var & 8) ? 1 : (draw_var & 16) ? 2 : (draw_
var & 32) ? 3 : (draw_var & 64) ? 4 : 0;
float font_size = SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting,
cSetting_label_size);
float tCenter[4], sCenter[4], sTarget[4];
short relativeMode = ((short)*(v + 15));
copy3f(TextGetLabelPushPos(G), tCenter);
copy3f(tCenter, torigCenter);
TextSetPosNColor(G, tCenter, v);
RayGetScaledAllAxesAtPoint(ray, tCenter, xn, yn, zn);
copy3f(v + 3, tTarget);
tCenter[3] = 1.f;
tTarget[3] = 1.f;
v_scale = RayGetScreenVertexScale(ray,torigCenter);
RayGetScreenVertex(ray, tCenter, sCenter);
if (relativeMode & 8){ // label_z_target, adjust z to target
RayGetScreenVertex(ray, tTarget, sTarget);
} else {
// need to bring tTarget into same z as tCenter to measure
copy3f(tTarget, sTarget);
sTarget[3] = 1.f;
RayAdjustZtoScreenZofPoint(ray, sTarget, tCenter);
RayGetScreenVertex(ray, sTarget, sTarget);
}
subtract3f(sTarget, sCenter, tVec);
dVectorInPixels[0] = (tVec[0]-screenWorldOffset[0])/v_scale;
dVectorInPixels[1] = (tVec[1]-screenWorldOffset[1])/v_scale;
dVector[0] = (dVectorInPixels[0] / text_width) - indentFactor[0];
dVector[1] = (dVectorInPixels[1] / text_height) - indentFactor[1];
doNotDraw = ((fabs(dVector[0])) <= .5f && (fabs(dVector[1])) <= .5f) ? 1.f : 0
.f;
if (!(draw_var & 1) || doNotDraw > .5f)
drawLine = false;
mult3f(xn, indentFactor[0] * text_width + 2.f * (screenWorldOffset[0] / v_scal
e), tmp3f);
add3f(tmp3f, torigCenter, torigCenter);
mult3f(yn, indentFactor[1] * text_height + 2.f * (screenWorldOffset[1] / v_sca
le), tmp3f);
add3f(tmp3f, torigCenter, torigCenter);
mult3f(zn, -1.f, tmp3f); // push background back, not sure if this is needed,
doesn't hurt
add3f(tmp3f, torigCenter, torigCenter);
if (draw_var & 6){ // draw background or background outline
float tmpf[4][4] ;
float hwidth = ray->Sampling * text_width / 2.f, hheight = ray->Sampling * t
ext_height / 2.f;
addXYtoVertex(hwidth, hheight, xn, yn, torigCenter, tmpf[0]);
addXYtoVertex(hwidth, -hheight, xn, yn, torigCenter, tmpf[1]);
addXYtoVertex(-hwidth, hheight, xn, yn, torigCenter, tmpf[2]);
addXYtoVertex(-hwidth, -hheight, xn, yn, torigCenter, tmpf[3]);
if (draw_var & 2){ // draw background
float trans = 1.f - v[22];
float tmpf2[4][4];
float tmpc[4][4];
float lw2;
if (draw_var & 4) {
lw2 = ray->Sampling * connector_width / 2.f;
} else {
lw2 = ray->Sampling;
}
addXYZtoVertex(-lw2, -lw2, -1.f, xn, yn, zn, tmpf[0], tmpf2[0]); // UL
addXYZtoVertex(-lw2, lw2, -1.f, xn, yn, zn, tmpf[1], tmpf2[1]); // LL
addXYZtoVertex(lw2, -lw2, -1.f, xn, yn, zn, tmpf[2], tmpf2[2]); // UR
addXYZtoVertex(lw2, lw2, -1.f, xn, yn, zn, tmpf[3], tmpf2[3]); // LR
MatrixTransformC44f4f(RotMatrix, tmpf[0], tmpc[0]);
MatrixTransformC44f4f(RotMatrix, tmpf[1], tmpc[1]);
MatrixTransformC44f4f(RotMatrix, tmpf[2], tmpc[2]);
MatrixTransformC44f4f(RotMatrix, tmpf[3], tmpc[3]);
tmpc[0][0] = tmpc[1][0];
tmpc[2][0] = tmpc[3][0];
tmpc[0][1] = tmpc[2][1];
tmpc[1][1] = tmpc[3][1];
copy2f(tmpc[0], labelTop.p1);
copy2f(tmpc[2], labelTop.p2);
copy2f(tmpc[3], labelBottom.p1);
copy2f(tmpc[1], labelBottom.p2);
copy2f(tmpc[2], labelLeft.p1);
copy2f(tmpc[3], labelLeft.p2);
copy2f(tmpc[1], labelRight.p1);
copy2f(tmpc[0], labelRight.p2);
ray->triangleTrans3fv(tmpf2[0], tmpf2[1], tmpf2[2], zn, zn, zn, &v[23], &v
[23], &v[23], trans, trans, trans);
ray->setLastToNoLighting(1);
ray->triangleTrans3fv(tmpf2[1], tmpf2[2], tmpf2[3], zn, zn, zn, &v[23], &v
[23], &v[23], trans, trans, trans);
ray->setLastToNoLighting(1);
}
if (draw_var & 4){ // draw background outline
if (label_con_flat){
float tmpfs[4][4] ;
float lw = ray->Sampling * connector_width/2.f, dirv[3];
tmpf[0][3] = tmpf[1][3] = tmpf[2][3] = tmpf[3][3] = 0.f;
MatrixTransformC44f4f(ray->ModelView, tmpf[0], tmpfs[0]);
MatrixTransformC44f4f(ray->ModelView, tmpf[1], tmpfs[1]);
MatrixTransformC44f4f(ray->ModelView, tmpf[2], tmpfs[2]);
MatrixTransformC44f4f(ray->ModelView, tmpf[3], tmpfs[3]);
RayDrawLineAsGeometryWithOffsets(ray, tmpf[2], tmpf[0], tmpfs[2], tmpfs[0
], xn, yn, zn, lw, 1.f, 0.f, v + 9, dirv, 1);
RayDrawLineAsGeometryWithOffsets(ray, tmpf[1], tmpf[0], tmpfs[1], tmpfs[0
], xn, yn, zn, lw, 0.f, 1.f, v + 9, dirv, 1);
RayDrawLineAsGeometryWithOffsets(ray, tmpf[3], tmpf[1], tmpfs[3], tmpfs[1
], xn, yn, zn, lw, 0.f, 1.f, v + 9, dirv, 1);
RayDrawLineAsGeometryWithOffsets(ray, tmpf[3], tmpf[2], tmpfs[3], tmpfs[2
], xn, yn, zn, lw, 1.f, 0.f, v + 9, dirv, 1);
} else {
float lw = connector_width * ray->PixelRadius / 2.f;
ray->sausage3fv(tmpf[0], tmpf[1], lw, v + 9, v + 9);
ray->sausage3fv(tmpf[0], tmpf[2], lw, v + 9, v + 9);
ray->sausage3fv(tmpf[1], tmpf[3], lw, v + 9, v + 9);
ray->sausage3fv(tmpf[2], tmpf[3], lw, v + 9, v + 9);
}
}
}
switch (label_connector_mode){
case 0:
{
float hmid = (fabs(dVector[0]) >= .5) ? 0.f : 1.f;
float vmid = (fabs(dVector[1]) >= .5) ? 0.f : 1.f;
float right = (1.f - hmid) * ((dVector[0] > 0.f) ? 1.f : 0.f) + hmid * .5f
;
float top = (1.f - vmid) * ((dVector[1] > 0.f) ? 1.f : 0.f) + vmid * .5f;
xoff = 2.f * (right - .5);
yoff = 2.f * (top - .5);
}
break;
case 3:
{
short hmid = (fabs(dVector[0]) < 1.f);
short vmid = (fabs(dVector[1]) < 1.f);
float right, top;
if (hmid){
right = ((1.f + dVector[0]) / 2.f);
} else {
right = ((dVector[0] > 0.f) ? 1.f : 0.f);
}
if (vmid){
top = ((1.f + dVector[1]) / 2.f);
} else {
top = ((dVector[1] > 0.f) ? 1.f : 0.f);
}
xoff = 2.f * (right - .5);
yoff = 2.f * (top - .5);
}
break;
case 1:
{
float drawVectorN[2], absyx, notabsyx, dvxy, dvyx, hdir, vdir;
copy2f(dVector, drawVectorN);
normalize2f(drawVectorN);
absyx = fabs(drawVectorN[0]) >= fabs(drawVectorN[1]) ? 1.f : 0.f;
notabsyx = 1.f - absyx;
hdir = 2.f * ( ( (drawVectorN[0] > 0.f) ? 1.f : 0.f ) - .5f);
vdir = 2.f * ( ( (drawVectorN[1] > 0.f) ? 1.f : 0.f ) - .5f);
dvxy = dVector[0] / dVector[1];
dvyx = dVector[1] / dVector[0];
xoff = (absyx * hdir) + (notabsyx * vdir * dvxy);
yoff = (notabsyx * vdir) + (absyx * hdir * dvyx);
}
break;
case 2:
case 4:
if (drawLine){
float extLength, rightorig, right, top, xofforig;
float endpointExtendedOffBBX[3];
short label_connector_mode_4 = (label_connector_mode == 4);
short hmid = 0, vmid = 0;
if (label_connector_mode_4){
hmid = (fabs(dVector[0]) < 1.);
vmid = (fabs(dVector[1]) < 1.);
}
if (font_size < 0.f){
extLength = - (*(v + 27) * font_size / text_height) / v_scale;
} else {
extLength = *(v + 27) * font_size / text_height;
}
if (hmid){
rightorig = ((1.f + dVector[0])/2.f);
right = rightorig;
} else {
rightorig = dVector[0] >= 0.f ? 1.f : 0.f;
right = rightorig + (rightorig - .5f) * CLAMP_VALUE(fabs(dVector[0]*2.f)-
1.f, 0.f,
2.f * extLength * fab
s(text_height/(float)text_width));
}
if (vmid){
top = ((1.f + dVector[1])/2.f);
} else {
top = dVector[1] >= 0.f ? 1.f : 0.f;
}
xofforig = 2. * (rightorig - .5);
xoff = 2.f * (right - .5);
yoff = 2.f * (top - .5);
mult3f(xn, xofforig * text_width, endpointOnBBX);
mult3f(yn, yoff * text_height, tmp3f);
add3f(tmp3f, endpointOnBBX, endpointOnBBX);
add3f(torigCenter, endpointOnBBX, endpointOnBBX);
mult3f(xn, xoff * text_width, endpointExtendedOffBBX);
mult3f(yn, yoff * text_height, tmp3f);
add3f(tmp3f, endpointExtendedOffBBX, endpointExtendedOffBBX);
add3f(torigCenter, endpointExtendedOffBBX, endpointExtendedOffBBX);
if (label_con_flat){
float tmpf[3][4] ;
float tmpfs[3][4] ;
float dirv1[3], dirv2[3], cross[3], pt[3][3];
copy3f(v + 3, tmpf[0]);
copy3f(endpointExtendedOffBBX, tmpf[1]);
copy3f(endpointOnBBX, tmpf[2]);
tmpf[0][3] = tmpf[1][3] = tmpf[2][3] = 0.f;
MatrixTransformC44f4f(ray->ModelView, tmpf[0], tmpfs[0]);
MatrixTransformC44f4f(ray->ModelView, tmpf[1], tmpfs[1]);
MatrixTransformC44f4f(ray->ModelView, tmpf[2], tmpfs[2]);
RayDrawLineAsGeometryWithOffsets(ray, tmpf[0], tmpf[1], tmpfs[0], tmpfs[1
], xn, yn, zn, connector_width, 0.f, 0.f, v + 9, dirv1, 1);
RayDrawLineAsGeometryWithOffsets(ray, tmpf[1], tmpf[2], tmpfs[1], tmpfs[2
], xn, yn, zn, connector_width, 0.f, 0.f, v + 9, dirv2, 1);
/* need to draw triangle to fill in gap */
dirv1[2] = dirv2[2] = 0.f;
cross_product3f(dirv1, dirv2, cross);
copy3f(endpointExtendedOffBBX, pt[0]);
copy3f(endpointExtendedOffBBX, pt[1]);
copy3f(endpointExtendedOffBBX, pt[2]);
if (cross[2] < 0.f){
addXYtoVertex(dirv1[0], dirv1[1], xn, yn, pt[1], pt[1]);
addXYtoVertex(dirv2[0], dirv2[1], xn, yn, pt[2], pt[2]);
} else {
addXYtoVertex(-dirv2[0], -dirv2[1], xn, yn, pt[1], pt[1]);
addXYtoVertex(-dirv1[0], -dirv1[1], xn, yn, pt[2], pt[2]);
}
ray->triangle3fv(pt[0], pt[1], pt[2], zn, zn, zn, v + 9, v + 9, v + 9);
ray->setLastToNoLighting(1);
} else {
float lw = connector_width * ray->PixelRadius / 2.f;
ray->sausage3fv(v + 3, endpointExtendedOffBBX, lw, v + 9, v + 9);
ray->sausage3fv(endpointExtendedOffBBX, endpointOnBBX, lw, v + 9, v + 9);
}
drawLine = 0;
}
break;
}
if (drawLine){
mult3f(xn, xoff * text_width, endpointOnBBX);
mult3f(yn, yoff * text_height, tmp3f);
add3f(tmp3f, endpointOnBBX, endpointOnBBX);
add3f(torigCenter, endpointOnBBX, endpointOnBBX);
if (label_con_flat){
unsigned char drawDefaultLine = true;
if ( (draw_var & 2) && (label_connector_mode > 0) ){ // draw background
float tmpff[3][4];
float tmpfs[3][4];
float tmpfc[4][4];
float dirv1[3], dirv2[3];
float cw = connector_width;
float pt1E[3], pt2E[3];
float tmpV[3], tmpV2[3], tmpV3[3], tmpV4[3], linev2[3];
float nzn[3] = { 0.f, 0.f, 1.f };
lineSeg_t l1, l2;
float tmptrn[4][4];
float isec1[3], isec2[3];
int l1V = 0, l2V = 0;
copy3f(v + 3, tmpff[0]);
copy3f(endpointOnBBX, tmpff[1]);
copy3f(torigCenter, tmpff[2]);
tmpff[0][3] = tmpff[1][3] = tmpff[2][3] = 0.f;
MatrixTransformC44f4f(ray->ModelView, tmpff[0], tmpfs[0]);
MatrixTransformC44f4f(ray->ModelView, tmpff[1], tmpfs[1]);
MatrixTransformC44f4f(ray->ModelView, tmpff[2], tmpfs[2]);
copy3f(tmpff[0], pt1E);
copy3f(tmpff[1], pt2E);
subtract3f(tmpfs[0], tmpfs[1], tmpV);
subtract3f(tmpfs[1], tmpfs[2], tmpV2);
copy3f(tmpV2, linev2);
normalize3f(linev2);
mult3f(linev2, cw * 10.0f, linev2);
cross_product3f(tmpV, nzn, tmpV3);
cross_product3f(tmpV2, nzn, tmpV4);
normalize3f(tmpV3);
normalize3f(tmpV4);
mult3f(tmpV3, cw, dirv1);
mult3f(tmpV4, cw, dirv2);
addXYtoVertex(dirv2[0], dirv2[1], xn, yn, tmpff[1], tmptrn[0]);
addXYtoVertex(linev2[0], linev2[1], xn, yn, tmptrn[0], tmptrn[0]);
addXYtoVertex(-dirv2[0], -dirv2[1], xn, yn, tmpff[1], tmptrn[1]);
addXYtoVertex(linev2[0], linev2[1], xn, yn, tmptrn[1], tmptrn[1]);
addXYtoVertex(dirv2[0], dirv2[1], xn, yn, tmpff[2], tmptrn[2]);
addXYtoVertex(-dirv2[0], -dirv2[1], xn, yn, tmpff[2], tmptrn[3]);
MatrixTransformC44f4f(RotMatrix, tmptrn[0], tmpfc[0]);
MatrixTransformC44f4f(RotMatrix, tmptrn[1], tmpfc[1]);
MatrixTransformC44f4f(RotMatrix, tmptrn[2], tmpfc[2]);
MatrixTransformC44f4f(RotMatrix, tmptrn[3], tmpfc[3]);
copy2f(tmpfc[0], l1.p1);
copy2f(tmpfc[1], l2.p1);
copy2f(tmpfc[2], l1.p2);
copy2f(tmpfc[3], l2.p2);
isec1[0] = isec1[1] = isec2[0] = isec2[1] = 0.f;
isec1[2] = isec2[2] = tmpfc[3][2];
if (lineSegIntersection(labelTop.p1, labelTop.p2, l1.p1, l1.p2, isec1)) {
l1V = 1;
} else if (lineSegIntersection(labelRight.p1, labelRight.p2, l1.p1, l1.p2
, isec1)) {
l1V = 2;
} else if (lineSegIntersection(labelBottom.p1, labelBottom.p2, l1.p1, l1.
p2, isec1)) {
l1V = 3;
} else if (lineSegIntersection(labelLeft.p1, labelLeft.p2, l1.p1, l1.p2,
isec1)) {
l1V = 4;
}
if (lineSegIntersection(labelTop.p1, labelTop.p2, l2.p1, l2.p2, isec2)) {
l2V = 1;
} else if (lineSegIntersection(labelRight.p1, labelRight.p2, l2.p1, l2.p2
, isec2)) {
l2V = 2;
} else if (lineSegIntersection(labelBottom.p1, labelBottom.p2, l2.p1, l2.
p2, isec2)) {
l2V = 3;
} else if (lineSegIntersection(labelLeft.p1, labelLeft.p2, l2.p1, l2.p2,
isec2)) {
l2V = 4;
}
// Both lines run through one side
if ( (l1V && l2V) ){
drawDefaultLine = false;
if ( l1V == l2V ) {
float isec1w[3], isec2w[3];
MatrixInvTransformC44fAs33f3f(RotMatrix, isec1, isec1w);
MatrixInvTransformC44fAs33f3f(RotMatrix, isec2, isec2w);
addXYtoVertex(dirv1[0], dirv1[1], xn, yn, tmpff[0], pt1E);
addXYtoVertex(-dirv1[0], -dirv1[1], xn, yn, tmpff[0], pt2E);
ray->triangle3fv(pt1E, pt2E, isec1w, zn, zn, zn, v + 9, v + 9, v + 9)
;
ray->triangle3fv(pt2E, isec1w, isec2w, zn, zn, zn, v + 9, v + 9, v +
9);
} else { // (l1V != l2V)
float isecc[3];
float isec1w[3], isec2w[3], iseccw[3];
isecc[2] = isec1[2];
// Find the corner
if ( (l1V == 1 && l2V == 2) || (l1V == 2 && l2V == 1) ) { // UR
isecc[0] = labelTop.p1[0];
isecc[1] = labelTop.p1[1];
} else if ( (l1V == 2 && l2V == 3) || (l1V == 3 && l2V == 2) ) { // L
R
isecc[0] = labelBottom.p2[0];
isecc[1] = labelBottom.p2[1];
} else if ( (l1V == 3 && l2V == 4) || (l1V == 4 && l2V == 3) ) { // L
L
isecc[0] = labelBottom.p1[0];
isecc[1] = labelBottom.p1[1];
} else if ( (l1V == 4 && l2V == 1) || (l1V == 1 && l2V == 4) ) { // U
L
isecc[0] = labelTop.p2[0];
isecc[1] = labelTop.p2[1];
}
MatrixInvTransformC44fAs33f3f(RotMatrix, isec1, isec1w);
MatrixInvTransformC44fAs33f3f(RotMatrix, isec2, isec2w);
MatrixInvTransformC44fAs33f3f(RotMatrix, isecc, iseccw);
addXYtoVertex(dirv1[0], dirv1[1], xn, yn, tmpff[0], pt1E);
addXYtoVertex(-dirv1[0], -dirv1[1], xn, yn, tmpff[0], pt2E);
ray->triangle3fv(isec1w, pt1E, iseccw, zn, zn, zn, v + 9, v + 9, v +
9);
ray->triangle3fv(pt1E, iseccw, pt2E, zn, zn, zn, v + 9, v + 9, v + 9)
;
ray->triangle3fv(iseccw, pt2E, isec2w, zn, zn, zn, v + 9, v + 9, v +
9);
}
}
}
if (drawDefaultLine){
float tmpf[2][4] ;
float tmpfs[2][4], dirv[3] ;
copy3f(v + 3, tmpf[0]);
copy3f(endpointOnBBX, tmpf[1]);
tmpf[0][3] = tmpf[1][3] = 0.f;
MatrixTransformC44f4f(ray->ModelView, tmpf[0], tmpfs[0]);
MatrixTransformC44f4f(ray->ModelView, tmpf[1], tmpfs[1]);
RayDrawLineAsGeometryWithOffsets(ray, tmpf[0], tmpf[1], tmpfs[0], tmpfs[1
], xn, yn, zn, connector_width, 0.f, 0.f, v + 9, dirv, 1);
}
} else {
ray->sausage3fv(v + 3, endpointOnBBX, connector_width * ray->PixelRadius /
2.f, v + 9, v + 9);
}
}
}
static
void RepLabelRenderRay(RepLabel * I, RenderInfo * info){
#ifndef _PYMOL_NO_RAY
PyMOLGlobals *G = I->R.G;
CRay *ray = info->ray;
int c = I->N;
float *v = I->V;
int *l = I->L;
int font_id = SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting,
cSetting_label_font_id);
float font_size = SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting,
cSetting_label_size);
if(c) {
char *st;
TextSetOutlineColor(G, I->OutlineColor);
while(c--) {
if(*l) {
float xn[3], yn[3], tCenter[3], offpt[3];
short relativeMode = ((short)*(v + 15));
int draw_var = 127 & (int)*(v + 21);
copy3f(v + 6, tCenter);
SceneGetCenter(G, offpt);
RayGetScaledAxes(ray, xn, yn);
st = OVLexicon_FetchCString(G->Lexicon, *l);
TextSetLabelBkgrdInfo(G, *(v + 16), *(v + 17), (v + 18));
if (relativeMode & 8){ // label_z_target, adjust z to target
TextGetLabelPos(G)[0] = (SceneGetDepth(G, v+3) - .5) * 2.f;
TextSetLabelPosIsSet(G, 1);
} else if (relativeMode & 6){ // label_relative_mode 1 or 2, i.e., scree
n stabilized, adjust z
if (relativeMode & 4){ // label_relative_mode = 2
tCenter[0] = (tCenter[0] / ray->Width) * 2.f - 1.f;
tCenter[1] = (tCenter[1] / ray->Height) * 2.f - 1.f;
}
TextSetLabelPos(G, tCenter);
TextSetLabelPosIsSet(G, 2);
float tmp3f[3];
mult3f(xn, tCenter[0] * ray->Width, tmp3f);
add3f(tmp3f, offpt, offpt);
mult3f(yn, tCenter[1] * ray->Height, tmp3f);
add3f(tmp3f, offpt, offpt);
copy3f(offpt, tCenter);
} else {
TextSetLabelPosIsSet(G, 0);
}
TextSetPosNColor(G, tCenter, v);
TextRenderRay(G, ray, font_id, st, font_size, v + 12, (draw_var ? 1 : 0)
, ((short)*(v + 15)));
if (draw_var){
RepLabelRenderRayBackground(I, info, v, draw_var);
}
}
v += 28;
l++;
}
}
#endif
}
static void RepLabelRender(RepLabel * I, RenderInfo * info) static void RepLabelRender(RepLabel * I, RenderInfo * info)
{ {
CRay *ray = info->ray; CRay *ray = info->ray;
Picking **pick = info->pick; Picking **pick = info->pick;
PyMOLGlobals *G = I->R.G; PyMOLGlobals *G = I->R.G;
float *v = I->V; float *v = I->V;
int c = I->N; int c = I->N;
int *l = I->L; int *l = I->L;
int font_id = SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting, int font_id = SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting,
cSetting_label_font_id); cSetting_label_font_id);
float font_size = SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting, float font_size = SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting,
cSetting_label_size); cSetting_label_size);
int float_text = SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting,
cSetting_float_labels);
if (!(ray || pick) && info->pass >= 0)
return;
if(ray) { if(I->R.MaxInvalid >= cRepInvRep){
if(c) { return;
char *st; }
TextSetOutlineColor(G, I->OutlineColor); font_id = SettingCheckFontID(G, I->R.cs->Setting, I->R.obj->Setting, font_id);
while(c--) {
if(*l) { if (I->shaderCGO && font_size < 0.f){
st = OVLexicon_FetchCString(G->Lexicon, *l); int size;
TextSetPosNColor(G, v + 3, v); if (InvalidateShaderCGOIfTextureNeedsUpdate(G, font_size, I->texture_font_si
TextRenderRay(G, ray, font_id, st, font_size, v + 6); ze, &size)){
} CGOFree(I->shaderCGO);
v += 9; I->texture_font_size = size;
l++;
}
} }
}
if(ray) {
RepLabelRenderRay(I, info);
} else if(G->HaveGUI && G->ValidContext) { } else if(G->HaveGUI && G->ValidContext) {
if(pick) { if(pick) {
Pickable *p = I->R.P; int pick_labels = SettingGet_b(G, I->R.cs->Setting, I->R.obj->Setting, cSe
int i; tting_pick_labels);
if (I->shaderCGO){ if (!pick_labels)
CGORenderGLPicking(I->shaderCGO, pick, &I->R.context, I->R.cs->Setting, I
->R.obj->Setting);
return; return;
} if (I->shaderCGO){
SceneSetupGLPicking(G);
if(c) {
char *st;
int float_text = SettingGetGlobal_i(G, cSetting_float_labels);
if(float_text) if(float_text)
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
CGORenderGLPicking(I->shaderCGO, info, &I->R.context, I->R.cs->Setting, I
->R.obj->Setting);
if(float_text)
glEnable(GL_DEPTH_TEST);
return;
} else {
Pickable *p = I->R.P;
unsigned int i;
TextSetIsPicking(G, true);
SceneSetupGLPicking(G);
if(c) {
char *st;
int screenwidth, screenheight;
if(float_text)
glDisable(GL_DEPTH_TEST);
i = (*pick)->src.index; if (!I->shaderCGO){
while(c--) { SceneGetWidthHeight(G, &screenwidth, &screenheight);
if(*l) { }
int first_pass = (!(*pick)[0].src.bond); i = (*pick)->src.index;
i++;
TextSetPosNColor(G, v + 3, v); while(c--) {
TextSetPickColor(G, first_pass, i); if(*l) {
if(first_pass) { float xn[3], yn[3], tCenterPt[3], offpt[3];
VLACheck((*pick), Picking, i); short relativeMode = ((short)*(v + 15));
p++; copy3f(v + 6, tCenterPt);
(*pick)[i].src = *p; /* copy object and atom info */ SceneGetCenter(G, offpt);
(*pick)[i].context = I->R.context; TextSetPosNColor(G, offpt, v);
SceneGetScaledAxes(G, I->R.obj, xn, yn);
if (!I->shaderCGO){
if (relativeMode & 2){ // label_relative_mode = 1
float tmp3f[3];
mult3f(xn, tCenterPt[0] * screenwidth/2.f, tmp3f);
add3f(tmp3f, offpt, offpt);
mult3f(yn, tCenterPt[1] * screenheight/2.f, tmp3f);
add3f(tmp3f, offpt, offpt);
copy3f(offpt, tCenterPt);
} else if (relativeMode & 4){ // label_relative_mode = 2
float tmp3f[3];
mult3f(xn, (tCenterPt[0] - (.5f * screenwidth)), tmp3f);
add3f(tmp3f, offpt, offpt);
mult3f(yn, (tCenterPt[1] - (.5f * screenheight)), tmp3f);
add3f(tmp3f, offpt, offpt);
copy3f(offpt, tCenterPt);
}
}
i++;
TextSetPosNColor(G, tCenterPt, v);
TextSetTargetPos(G, v + 3);
TextSetLabelBkgrdInfo(G, *(v + 16), *(v + 17), (v + 18));
if (p) {
p++;
AssignNewPickColor(NULL, i, pick, &I->R.context, TextGetColorUCh
ar4uv(G), p->index, p->bond);
}
TextSetColorFromUColor(G);
st = OVLexicon_FetchCString(G->Lexicon, *l);
if (!TextRenderOpenGL(G, info, font_id, st, font_size, v + 12, fal
se, (short)*(v + 15), 1, SHADERCGO)){
TextSetIsPicking(G, false);
return ;
}
} }
st = OVLexicon_FetchCString(G->Lexicon, *l); l++;
TextRenderOpenGL(G, info, font_id, st, font_size, v + 6, SHADERCGO); v += 28;
} }
l++; if(float_text)
v += 9; glEnable(GL_DEPTH_TEST);
(*pick)[0].src.index = i; /* pass the count */
} }
if(float_text) TextSetIsPicking(G, false);
glEnable(GL_DEPTH_TEST);
(*pick)[0].src.index = i; /* pass the count */
} }
} else { } else { // not pick or ray, render
if(c) { if(c) {
char *st; char *st;
int float_text = SettingGetGlobal_i(G, cSetting_float_labels); short use_shader, has_connector = 0;
short use_shader; CGO *connectorCGO = NULL;
float *PmvMatrix = NULL;
int screenwidth, screenheight;
float xn[3] = { 1.0F, 0.0F, 0.0F };
float yn[3] = { 0.0F, 1.0F, 0.0F };
int pre_use_shaders = info->use_shaders;
Pickable *p = I->R.P; Pickable *p = I->R.P;
use_shader = SettingGetGlobal_b(G, cSetting_use_shaders); use_shader = SettingGetGlobal_b(G, cSetting_use_shaders)
if(float_text) #ifdef _PYMOL_IOS
glDisable(GL_DEPTH_TEST); ;
#else
&& G->ShaderMgr->GeometryShadersPresent();
#endif
info->use_shaders = use_shader;
if (use_shader){ if (use_shader){
if (!I->shaderCGO){ if (!I->shaderCGO){
I->shaderCGO = CGONew(G); I->shaderCGO = CGONew(G);
if (use_shader){ I->shaderCGO->use_shader = true;
I->shaderCGO->use_shader = true;
I->shaderCGO->enable_shaders = true;
}
} else { } else {
info->texture_font_size = I->texture_font_size;
if(float_text)
glDisable(GL_DEPTH_TEST);
CGORenderGL(I->shaderCGO, NULL, NULL, NULL, info, &I->R); CGORenderGL(I->shaderCGO, NULL, NULL, NULL, info, &I->R);
if(float_text) if(float_text)
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
return; return;
} }
} else if (I->shaderCGO) { } else {
CGOFree(I->shaderCGO); CGOFree(I->shaderCGO);
I->shaderCGO = NULL;
#ifndef PURE_OPENGL_ES_2
if(!info->line_lighting)
glDisable(GL_LIGHTING);
#endif
} }
TextSetOutlineColor(G, I->OutlineColor); TextSetOutlineColor(G, I->OutlineColor);
if (I->shaderCGO && c){
connectorCGO = CGONew(G);
CGOBegin(connectorCGO, GL_LINES);
}
if (!I->shaderCGO){
PmvMatrix = SceneGetPmvMatrix(G);
SceneGetWidthHeight(G, &screenwidth, &screenheight);
MatrixInvTransformC44fAs33f3f(PmvMatrix, xn, xn);
MatrixInvTransformC44fAs33f3f(PmvMatrix, yn, yn);
normalize3f(xn);
normalize3f(yn);
}
while(c--) { while(c--) {
if(*l) { if(*l) {
p++; float tCenterPt[3], offpt[3];
if (I->shaderCGO) short relativeMode = ((short)*(v + 15));
CGOPickColor(I->shaderCGO, p->index, p->bond); int draw_var = 127 & (int)*(v + 21);
TextSetPosNColor(G, v + 3, v); copy3f(v + 6, tCenterPt);
SceneGetCenter(G, offpt);
TextSetPosNColor(G, offpt, v);
SceneGetScaledAxes(G, I->R.obj, xn, yn);
if (!I->shaderCGO){
if (relativeMode & 2){ // label_relative_mode = 1
float tmp3f[3];
mult3f(xn, tCenterPt[0] * screenwidth/2.f, tmp3f);
add3f(tmp3f, offpt, offpt);
mult3f(yn, tCenterPt[1] * screenheight/2.f, tmp3f);
add3f(tmp3f, offpt, offpt);
copy3f(offpt, tCenterPt);
} else if (relativeMode & 4){ // label_relative_mode = 2
float tmp3f[3];
mult3f(xn, (tCenterPt[0] - .5f * screenwidth), tmp3f);
add3f(tmp3f, offpt, offpt);
mult3f(yn, (tCenterPt[1] - .5f * screenheight), tmp3f);
add3f(tmp3f, offpt, offpt);
copy3f(offpt, tCenterPt);
}
}
if (p) {
p++;
if (I->shaderCGO)
CGOPickColor(I->shaderCGO, p->index, p->bond);
}
TextSetPosNColor(G, tCenterPt, v);
TextSetTargetPos(G, v + 3);
st = OVLexicon_FetchCString(G->Lexicon, *l); st = OVLexicon_FetchCString(G->Lexicon, *l);
TextRenderOpenGL(G, info, font_id, st, font_size, v + 6, SHADERCGO); TextSetLabelBkgrdInfo(G, *(v + 16), *(v + 17), (v + 18));
if (relativeMode & 8){ // label_z_target, adjust z to target
TextGetLabelPos(G)[0] = (SceneGetDepth(G, v+3) - .5) * 2.f;
TextSetLabelPosIsSet(G, 1);
} else if (relativeMode & 6){ // label_relative_mode 1 or 2, i.e., sc
reen stabilized, adjust z
TextSetLabelPos(G, v+6);
TextSetLabelPosIsSet(G, 2);
#ifndef PURE_OPENGL_ES_2
glDisable(GL_FOG);
#endif
} else {
TextSetLabelPosIsSet(G, 0);
}
#ifndef PURE_OPENGL_ES_2
if (!use_shader)
glPushMatrix();
#endif
if (!TextRenderOpenGL(G, info, font_id, st, font_size, v + 12, (draw
_var ? 1 : 0), (short)*(v + 15), use_shader, SHADERCGO)){
CGOFree(connectorCGO);
return;
}
if (draw_var){
float *RotMatrix = NULL;
float *screenWorldOffset = TextGetScreenWorldOffset(G);
float text_width = TextGetWidth(G), text_height = TextGetHeight(G);
float *indentFactor = TextGetIndentFactor(G);
RotMatrix = SceneGetMatrix(G);
if (I->shaderCGO){
CGODrawConnector(connectorCGO, v + 3, v + 6, text_width, text_hei
ght, indentFactor, screenWorldOffset, v + 9, ((short)*(v + 15)), draw_var, *(v +
22), (v + 23), *(v + 27) * font_size / text_height, *(v + 26)) ;
has_connector = 1;
} else {
#ifndef PURE_OPENGL_ES_2
RepLabelRenderBackgroundInImmediate(G, I, v, draw_var, tCenterPt,
relativeMode, xn, yn, PmvMatrix, RotMatrix, screenwidth, screenheight, screenWo
rldOffset, indentFactor, text_width, text_height, font_size);
#endif
}
}
#ifdef PURE_OPENGL_ES_2
if (float_text && draw_var){
TextRenderOpenGL(G, info, font_id, st, font_size, v + 12, 1, (short
)*(v + 15), 1, SHADERCGO);
}
#else
if (!use_shader){
glPopMatrix();
{
// for now, render text twice in immediate mode, some cards don't
handle
// z-buffer offset properly, before, only did this when float_tex
t && draw_var
glPushMatrix();
TextRenderOpenGL(G, info, font_id, st, font_size, v + 12, 1, (sho
rt)*(v + 15), 1, SHADERCGO);
glPopMatrix();
}
}
#endif
if (relativeMode & 6){ // label_relative_mode 1 or 2, i.e., screen st
abilized, adjust z
#ifndef PURE_OPENGL_ES_2
glEnable(GL_FOG);
#endif
}
} }
l++; l++;
v += 9; v += 28;
} }
if (!has_connector){
CGOFree(connectorCGO);
}
if (connectorCGO){
CGOEnd(connectorCGO);
CGOStop(connectorCGO);
}
if (I->shaderCGO){ if (I->shaderCGO){
CGO *convertcgo; CGO *totalCGO = NULL;
CGO *labelCGO = NULL;
CGOStop(I->shaderCGO); CGOStop(I->shaderCGO);
convertcgo = CGOOptimizeLabels(I->shaderCGO, 0); CGO * tmpCGO = CGONew(G);
CGOEnable(tmpCGO, GL_LABEL_SHADER);
CGOSpecial(tmpCGO, SET_LABEL_SCALE_UNIFORMS);
labelCGO = CGOConvertToLabelShader(I->shaderCGO, tmpCGO);
CGOAppendNoStop(tmpCGO, labelCGO);
CGOFreeWithoutVBOs(labelCGO);
labelCGO = tmpCGO;
if (!labelCGO) return;
CGOFree(I->shaderCGO); CGOFree(I->shaderCGO);
I->shaderCGO = convertcgo; if (connectorCGO){
convertcgo = NULL; CGO *tmpCGO = NULL;
tmpCGO = CGOOptimizeConnectors(connectorCGO, 0);
CGOFree(connectorCGO);
connectorCGO = tmpCGO;
// need to render connector/backgrounds first
totalCGO = CGONew(G);
CGOEnable(totalCGO, GL_LABEL_FLOAT_TEXT);
CGOEnable(totalCGO, GL_CONNECTOR_SHADER);
#ifndef PURE_OPENGL_ES_2
CGODisable(totalCGO, GL_LIGHTING);
#endif
CGOAppendNoStop(totalCGO, connectorCGO);
CGOFreeWithoutVBOs(connectorCGO);
CGODisable(totalCGO, GL_CONNECTOR_SHADER);
CGOAppendNoStop(totalCGO, labelCGO);
CGOFreeWithoutVBOs(labelCGO);
CGODisable(totalCGO, GL_LABEL_FLOAT_TEXT);
CGOStop(totalCGO);
} else {
totalCGO = CGONew(G);
CGOEnable(totalCGO, GL_LABEL_FLOAT_TEXT);
CGOAppendNoStop(totalCGO, labelCGO);
CGODisable(totalCGO, GL_LABEL_FLOAT_TEXT);
CGODisable(totalCGO, GL_LABEL_SHADER);
CGOStop(totalCGO);
CGOFreeWithoutVBOs(labelCGO);
}
I->shaderCGO = totalCGO;
if (I->shaderCGO){ if (I->shaderCGO){
I->shaderCGO->use_shader = true; I->shaderCGO->use_shader = true;
I->shaderCGO->enable_shaders = true; RepLabelRender(I, info);
CGORenderGL(I->shaderCGO, NULL, NULL, NULL, info, &I->R); return;
} }
} } else {
#ifndef PURE_OPENGL_ES_2
glEnable(GL_LIGHTING);
#endif
glEnable(GL_BLEND);
}
if(float_text) if(float_text)
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
info->use_shaders = pre_use_shaders;
} }
} }
} }
} }
Rep *RepLabelNew(CoordSet * cs, int state) Rep *RepLabelNew(CoordSet * cs, int state)
{ {
PyMOLGlobals *G = cs->State.G; PyMOLGlobals *G = cs->State.G;
ObjectMolecule *obj; ObjectMolecule *obj;
int a, a1, c1; int a, a1, c1;
float *v; float *v, *v0;
const float *v0, *vc; const float *vc;
const float *lab_pos;
int *l; int *l;
int label_color; int label_color;
LabPosType *lp = NULL;
Pickable *rp = NULL; Pickable *rp = NULL;
AtomInfoType *ai; AtomInfoType *ai;
// skip if no labels are visible // skip if no labels are visible
if(!cs->hasRep(cRepLabelBit)) if(!cs->hasRep(cRepLabelBit))
return NULL; return NULL;
OOAlloc(G, RepLabel); OOAlloc(G, RepLabel);
RepLabelInit(I); RepLabelInit(I);
obj = cs->Obj; obj = cs->Obj;
skipping to change at line 229 skipping to change at line 1538
I->R.fRecolor = NULL; I->R.fRecolor = NULL;
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 */
I->L = Alloc(int, cs->NIndex); I->L = Alloc(int, cs->NIndex);
ErrChkPtr(G, I->L); ErrChkPtr(G, I->L);
I->V = (float *) mmalloc(sizeof(float) * cs->NIndex * 9); I->V = Calloc(float, cs->NIndex * 28);
ErrChkPtr(G, I->V); ErrChkPtr(G, I->V);
I->OutlineColor = I->OutlineColor =
SettingGet_color(G, cs->Setting, obj->Obj.Setting, cSetting_label_outline_co lor); SettingGet_color(G, cs->Setting, obj->Obj.Setting, cSetting_label_outline_co lor);
lab_pos = SettingGet_3fv(G, cs->Setting, obj->Obj.Setting, cSetting_label_posi
tion);
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);
ErrChkPtr(G, I->R.P); ErrChkPtr(G, I->R.P);
rp = I->R.P + 1; /* skip first record! */ rp = I->R.P + 1; /* skip first record! */
} }
I->N = 0; I->N = 0;
v = I->V; v = I->V;
l = I->L; l = I->L;
for(a = 0; a < cs->NIndex; a++) { for(a = 0; a < cs->NIndex; a++) {
a1 = cs->IdxToAtm[a]; a1 = cs->IdxToAtm[a];
ai = obj->AtomInfo + a1; ai = obj->AtomInfo + a1;
if(cs->LabPos) {
lp = cs->LabPos + a;
}
if((ai->visRep & cRepLabelBit) && (ai->label)) { if((ai->visRep & cRepLabelBit) && (ai->label)) {
int at_label_color = AtomSettingGetWD(G, ai, cSetting_label_color, label_c olor); int at_label_color = AtomSettingGetWD(G, ai, cSetting_label_color, label_c olor);
/*
float at_label_pos = lab_pos;
AtomInfoGetSetting_3fv(G, ai, cSetting_label_position,
label_pos, &at_label_pos);
*/
I->N++; I->N++;
if((at_label_color >= 0) || if((at_label_color >= 0) ||
(at_label_color == cColorFront) || (at_label_color == cColorFront) ||
(at_label_color == cColorBack)) (at_label_color == cColorBack))
c1 = at_label_color; c1 = at_label_color;
else else
c1 = ai->color; c1 = ai->color;
/* V - Color, Coordinate, Coordinate + Offset (from label_placement_offset
), label_position) */
vc = ColorGet(G, c1); /* save new color */ vc = ColorGet(G, c1); /* save new color */
*(v++) = *(vc++); *(v++) = *(vc++);
*(v++) = *(vc++); *(v++) = *(vc++);
*(v++) = *(vc++); *(v++) = *(vc++);
v0 = cs->Coord + 3 * a; v0 = cs->Coord + 3 * a;
*(v++) = *(v0++); *(v++) = *(v0++);
*(v++) = *(v0++); *(v++) = *(v0++);
*(v++) = *(v0++); *(v++) = *(v0++);
if(lp) { {
switch (lp->mode) { const float *at_label_pos, *at_label_padding;
case 1: /* local absolute positioning, global relative */ const float *con_color;
add3f(lp->offset, v - 3, v - 3); float label_connector_width, label_connector_ext_length;
copy3f(lab_pos, v); int label_connector = 0, label_bg = 0, label_bg_outline = 0, at_con_color
break; = 0, at_label_relative_mode = 0, at_label_z_target,
default: label_connector_mode = 0, label_connector_mode_1 = 0, label_connector_m
copy3f(lab_pos, v); ode_2 = 0, label_connector_mode_3 = 0, label_connector_mode_4 = 0, ray_label_con
break; nector_flat = 0;
} float at_label_spacing, at_label_justification, at_label_bkgrd_transp;
} else { short drawConnector, isProjected, isScreenCoord, isPixelCoord;
copy3f(lab_pos, v); AtomStateGetSetting_i(G, obj, cs, a, ai, cSetting_label_relative_mode, &a
} t_label_relative_mode);
if (at_label_relative_mode){
const float * at_label_screen_point;
AtomStateGetSetting(G, obj, cs, a, ai, cSetting_label_screen_point, &at
_label_screen_point);
copy3f(at_label_screen_point, v);
RepLabelAdjustScreenZ(G, v);
} else {
const float * at_label_place;
AtomStateGetSetting(G, obj, cs, a, ai, cSetting_label_placement_offset,
&at_label_place);
add3f(at_label_place, v - 3, v);
}
v += 3;
AtomStateGetSetting_color(G, obj, cs, a, ai, cSetting_label_connector_col
or, &at_con_color);
v += 3; /* behave just like the label color */
if(!((at_con_color >= 0) ||
(at_con_color == cColorFront) ||
(at_con_color == cColorBack)))
at_con_color = ai->color;
con_color = ColorGet(G, at_con_color);
copy3f(con_color, v);
v += 3;
AtomStateGetSetting_b(G, obj, cs, a, ai, cSetting_ray_label_connector_fla
t, &ray_label_connector_flat);
AtomStateGetSetting_b(G, obj, cs, a, ai, cSetting_label_bg_outline, &labe
l_bg_outline);
AtomStateGetSetting_b(G, obj, cs, a, ai, cSetting_label_connector, &label
_connector);
AtomStateGetSetting_i(G, obj, cs, a, ai, cSetting_label_connector_mode, &
label_connector_mode);
AtomStateGetSetting_i(G, obj, cs, a, ai, cSetting_label_z_target, &at_lab
el_z_target);
AtomStateGetSetting(G, obj, cs, a, ai, cSetting_label_position, &at_label
_pos);
copy3f(at_label_pos, v);
v += 3;
AtomStateGetSetting_f(G, obj, cs, a, ai, cSetting_label_multiline_spacing
, &at_label_spacing);
AtomStateGetSetting_f(G, obj, cs, a, ai, cSetting_label_multiline_justifi
cation, &at_label_justification);
at_label_justification = CLAMP_VALUE(at_label_justification , -1.f, 1.f);
AtomStateGetSetting(G, obj, cs, a, ai, cSetting_label_padding, &at_label_
padding);
AtomStateGetSetting_f(G, obj, cs, a, ai, cSetting_label_bg_transparency,
&at_label_bkgrd_transp);
AtomStateGetSetting_color(G, obj, cs, a, ai, cSetting_label_bg_color, &at
_con_color);
label_bg = (at_con_color != -1) && (at_label_bkgrd_transp < 1.f); // if t
he color is not default and transparency is < 1., then draw bg
drawConnector = (label_connector > 0 || label_bg || label_bg_outline > 0)
? 1 : 0;
if (at_label_z_target < 0){
// defaults to z if draw connector
if (drawConnector){
at_label_z_target = 1;
} else {
at_label_z_target = 0;
}
} else {
at_label_z_target = at_label_z_target ? 1 : 0;
}
isProjected = (at_label_relative_mode < 1) ? 1 : 0;
isScreenCoord = (at_label_relative_mode == 1) ? 1 : 0;
isPixelCoord = (isProjected + isScreenCoord) ? 0 : 1;
*(v++) = (float)(drawConnector + isScreenCoord * 2 + isPixelCoord * 4 + a
t_label_z_target * 8);
*(v++) = at_label_spacing;
*(v++) = at_label_justification;
copy3f(at_label_padding, v);
v += 3;
label_connector_mode_1 = label_connector_mode == 1;
label_connector_mode_2 = label_connector_mode == 2;
label_connector_mode_3 = label_connector_mode == 3;
label_connector_mode_4 = label_connector_mode == 4;
*(v++) = (float)(label_connector + 2 * label_bg + 4 * label_bg_outline +
8 * label_connector_mode_1 +
16 * label_connector_mode_2 + 32 * label_connector_mode_
3 + 64 * label_connector_mode_4 + 128 * ray_label_connector_flat);
*(v++) = 1.f-at_label_bkgrd_transp;
/* behave just like the label color */
if(!((at_con_color >= 0) ||
(at_con_color == cColorFront) ||
(at_con_color == cColorBack)))
at_con_color = ai->color;
con_color = ColorGet(G, at_con_color);
copy3f(con_color, v);
v += 3;
AtomStateGetSetting_f(G, obj, cs, a, ai, cSetting_label_connector_width,
&label_connector_width);
*(v++) = DIP2PIXEL(label_connector_width);
AtomStateGetSetting_f(G, obj, cs, a, ai, cSetting_label_connector_ext_len
gth, &label_connector_ext_length);
*(v++) = label_connector_ext_length;
}
if(rp) { if(rp) {
rp->index = a1; rp->index = a1;
rp->bond = cPickableLabel; /* label indicator */ rp->bond = ai->masked ? cPickableNoPick : cPickableLabel; /* label indicator */
rp++; rp++;
} }
*(l++) = ai->label; *(l++) = ai->label;
} }
} }
if(I->N) { if(I->N) {
I->V = ReallocForSure(I->V, float, (v - I->V)); I->V = ReallocForSure(I->V, float, (v - I->V));
I->L = ReallocForSure(I->L, int, (l - I->L)); I->L = ReallocForSure(I->L, int, (l - I->L));
if(rp) { if(rp) {
 End of changes. 44 change blocks. 
103 lines changed or deleted 1613 lines changed or added

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