int ExtrudeCGOSurfaceStrand()

in layer1/Extrude.cpp [1712:2039]


int ExtrudeCGOSurfaceStrand(CExtrude * I, CGO * cgo, int sampling, const float *color_override)
{
  int a, b;
  unsigned int *i;
  float *v;
  float *n;
  float *c;
  const float *alpha;
  float *sv, *sn, *tv, *tn, *tv1, *tn1, *TV = NULL, *TN = NULL;
  float v0[3], n0[3], s0[3], z[3] = { 1.0, 0.0, 1.0 };
  int subN;
  int ok = true;
  subN = I->N - sampling;

  PRINTFD(I->G, FB_Extrude)
    " ExtrudeCGOSurfaceStrand-DEBUG: entered.\n" ENDFD;

  if(I->N && I->Ns) {

    TV = Alloc(float, 3 * (I->Ns + 1) * I->N);
    CHECKOK(ok, TV);
    if (ok)
      TN = Alloc(float, 3 * (I->Ns + 1) * I->N);
    CHECKOK(ok, TN);
    /* compute transformed shape vertices */

    if (ok){
      tn = TN;
      tv = TV;
      sv = I->sv;
      sn = I->sn;
      for(b = 0; b <= I->Ns; b++) {
	if(b == I->Ns) {
	  sv = I->sv;
	  sn = I->sn;
	}
	v = I->p;
	n = I->n;
	for(a = 0; a < I->N; a++) {
	  copy3f(sv, s0);
	  if(a == subN) {
	    scale3f(s0, 0.50F, s0);
	  }
	  transform33Tf3f(n, s0, tv);
	  add3f(v, tv, tv);
	  tv += 3;
	  transform33Tf3f(n, sn, tn);
	  tn += 3;
	  n += 9;
	  v += 3;
	}
	sv += 3;
	sn += 3;
      }

      /* fill in each strip of arrow separately */
      
      tv = TV;
      tn = TN;
      
      tv1 = TV + 3 * I->N;
      tn1 = TN + 3 * I->N;
    }

    for(b = 0; ok && b < I->Ns; b += 2) {
      if(SettingGetGlobal_i(I->G, cSetting_cartoon_debug) < 1.5)
        ok &= CGOBegin(cgo, GL_TRIANGLE_STRIP);
      else {
        ok &= CGOBegin(cgo, GL_LINE_STRIP);
      }
      c = I->c;
      alpha = I->alpha;
      i = I->i;
      for(a = 0; ok && a < I->N; a++) {
        if(a < subN) {
	  if(color_override && ((b == 2) || (b == 3) || (b == 6) || (b == 7)))
	    ok &= CGOColorv(cgo, color_override);
	  else
	    ok &= CGOColorv(cgo, c);
      if (ok){
        ok &= CGOAlpha(cgo, *alpha);
      }
	  if (ok)
	    ok &= CGOPickColor(cgo, *i, cPickableAtom);
	  if (ok)
	    ok &= CGONormalv(cgo, tn);
	  if (ok)
	    ok &= CGOVertexv(cgo, tv);
        }
        tn += 3;
        tv += 3;
        if(ok && a < subN) {
          ok &= CGONormalv(cgo, tn1);
	  if (ok)
	    ok &= CGOVertexv(cgo, tv1);
        }
        tn1 += 3;
        tv1 += 3;
        c += 3;
        alpha++;
        i++;
      }
      tv += 3 * I->N;
      tn += 3 * I->N;
      tv1 += 3 * I->N;
      tn1 += 3 * I->N;
      if (ok)
	ok &= CGOEnd(cgo);
      if (ok)
	ok &= CGOPickColor(cgo, -1, cPickableNoPick);
    }

    if(ok) {

      n = I->n;
      v = I->p;

      sv = I->sv;
      tv = I->tv;
      for(b = 0; b < I->Ns; b++) {
        transform33Tf3f(n, sv, tv);
        add3f(v, tv, tv);
        sv += 3;
        tv += 3;
      }

      copy3f(I->n, v0);
      invert3f(v0);
      if (ok){
	if(color_override)
	  ok &= CGOColorv(cgo, color_override);
	else
	  ok &= CGOColorv(cgo, I->c);
       }
      if(ok){
        ok &= CGOAlpha(cgo, I->alpha[0]);
      }
      if (ok)
	ok &= CGOPickColor(cgo, I->i[0], cPickableAtom);

      if (ok)
	ok &= CGOBegin(cgo, GL_TRIANGLE_STRIP);
      if (ok)
	ok &= CGONormalv(cgo, v0);

      ok &= CGOVertexv(cgo, I->tv + 6 * 3);
      ok &= CGOVertexv(cgo, I->tv + 4 * 3);
      ok &= CGOVertexv(cgo, I->tv + 0 * 3);
      ok &= CGOVertexv(cgo, I->tv + 2 * 3);
      if (ok)
	ok &= CGOEnd(cgo);
      if (ok)
	ok &= CGOPickColor(cgo, -1, cPickableNoPick);
    }

    /* now do the arrow part */

    tn = TN;
    tv = TV;

    sv = I->sv;
    sn = I->sn;
    if (ok){
      for(b = 0; b <= I->Ns; b++) {
	if(b == I->Ns) {
	  sv = I->sv;
	  sn = I->sn;
	}
	v = I->p;
	n = I->n;
	
	for(a = 0; a < I->N; a++) {
	  copy3f(sv, s0);
	  s0[2] = s0[2] * ((1.5F * ((I->N - 1) - a)) / sampling);
	  transform33Tf3f(n, s0, tv);
	  add3f(v, tv, tv);
	  tv += 3;
	  copy3f(sn, n0);
	  if(fabs(dot_product3f(sn, z)) > R_SMALL4) {
	    n0[0] += 0.4F;
	    normalize3f(n0);
	  }
	  transform33Tf3f(n, n0, tn);
	  tn += 3;
	  n += 9;
	  v += 3;
	}
	sv += 3;
	sn += 3;
      }
    }

    tv = TV;
    tn = TN;

    tv1 = TV + 3 * I->N;
    tn1 = TN + 3 * I->N;

    for(b = 0; ok && b < I->Ns; b += 2) {
      if (ok){
	if(SettingGetGlobal_i(I->G, cSetting_cartoon_debug) < 1.5)
	  ok &= CGOBegin(cgo, GL_TRIANGLE_STRIP);
	else {
	  ok &= CGOBegin(cgo, GL_LINE_STRIP);
	}
      }
      c = I->c;
      alpha = I->alpha;
      i = I->i;
      for(a = 0; ok && a < I->N; a++) {
        if(a >= (subN - 1)) {
          if(color_override && ((b == 2) || (b == 3) || (b == 6) || (b == 7)))
            ok &= CGOColorv(cgo, color_override);
          else
            ok &= CGOColorv(cgo, c);
        if (ok){
          ok &= CGOAlpha(cgo, *alpha);
        }
	  if (ok)
	    ok &= CGOPickColor(cgo, *i, cPickableAtom);
          if (ok)
	    ok &= CGONormalv(cgo, tn);
	  if (ok)
	    ok &= CGOVertexv(cgo, tv);
        }
        tn += 3;
        tv += 3;
        if(ok && a >= (subN - 1)) {
          ok &= CGONormalv(cgo, tn1);
	  if (ok)
	    ok &= CGOVertexv(cgo, tv1);
        }
        tn1 += 3;
        tv1 += 3;
        c += 3;
        alpha++;
        i++;
      }
      tv += 3 * I->N;
      tn += 3 * I->N;
      tv1 += 3 * I->N;
      tn1 += 3 * I->N;
      if (ok)
	ok &= CGOEnd(cgo);
      if (ok)
	ok &= CGOPickColor(cgo, -1, cPickableNoPick);
    }

    n = I->n + 9 * (subN - 1);
    v = I->p + 3 * (subN - 1);
    sv = I->sv;
    tv = I->tv;
    if (ok){
      for(b = 0; b < I->Ns; b++) {
	copy3f(sv, s0);
	s0[2] = s0[2] * ((s0[2] < 0.f) ? -1.f : 1.5F) ;
	transform33Tf3f(n, s0, tv);
	add3f(v, tv, tv);
	sv += 3;
	tv += 3;
      }
    }

    // Back end/flat surface of the arrow, 
    // now split into two pieces, one for each side
    copy3f(n, v0);
    invert3f(v0);
    if (ok){
      if(color_override)
	ok &= CGOColorv(cgo, color_override);
      else
	ok &= CGOColorv(cgo, I->c + 3 * (subN - 1));
    }
    if (ok){
      ok &= CGOAlpha(cgo, I->alpha[(subN - 1)]);
    }
    if (ok)
      ok &= CGOPickColor(cgo, I->i[(subN - 1)], cPickableAtom);

    // draw first side
    tv = I->tv;
    if (ok)
      ok &= CGOBegin(cgo, GL_TRIANGLE_STRIP);
    if (ok)
      ok &= CGONormalv(cgo, v0);
    ok &= CGOVertexv(cgo, I->tv + 6 * 3);
    ok &= CGOVertexv(cgo, I->tv + 4 * 3);
    ok &= CGOVertexv(cgo, I->tv + 0 * 3);
    ok &= CGOVertexv(cgo, I->tv + 2 * 3);
    if (ok)
      ok &= CGOEnd(cgo);

    // switch vertices to other side of flat surface of arrow
    sv = I->sv;
    tv = I->tv;
    if (ok){
      for(b = 0; b < I->Ns; b++) {
	copy3f(sv, s0);
	s0[2] = s0[2] * ((s0[2] < 0.f) ? 1.f : -1.5F) ;
	transform33Tf3f(n, s0, tv);
	add3f(v, tv, tv);
	sv += 3;
	tv += 3;
      }
    }
    // draw other side
    if (ok)
      ok &= CGOBegin(cgo, GL_TRIANGLE_STRIP);
    if (ok)
      ok &= CGONormalv(cgo, v0);
    ok &= CGOVertexv(cgo, I->tv + 0 * 3);
    ok &= CGOVertexv(cgo, I->tv + 2 * 3);
    ok &= CGOVertexv(cgo, I->tv + 6 * 3);
    ok &= CGOVertexv(cgo, I->tv + 4 * 3);
    if (ok)
      ok &= CGOEnd(cgo);

    if (ok)
      ok &= CGOPickColor(cgo, -1, cPickableNoPick);

    FreeP(TV);
    FreeP(TN);
  }

  PRINTFD(I->G, FB_Extrude)
    " ExtrudeCGOSurfaceStrand-DEBUG: exiting...\n" ENDFD;
  return ok;
}