static void RepLabelRenderRayBackground()

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);
    }
  }
}