in layer2/RepLabel.cpp [705:1107]
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_scale), tmp3f);
add3f(tmp3f, torigCenter, torigCenter);
mult3f(yn, indentFactor[1] * text_height + 2.f * (screenWorldOffset[1] / v_scale), 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 * text_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 * fabs(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) ) { // LR
isecc[0] = labelBottom.p2[0];
isecc[1] = labelBottom.p2[1];
} else if ( (l1V == 3 && l2V == 4) || (l1V == 4 && l2V == 3) ) { // LL
isecc[0] = labelBottom.p1[0];
isecc[1] = labelBottom.p1[1];
} else if ( (l1V == 4 && l2V == 1) || (l1V == 1 && l2V == 4) ) { // UL
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);
}
}
}