示例#1
0
void cone (Scene &scene, int nseg, const Trafo& P, const ColorB* color) 
//
// Adds a unit cone of radius 1 in x-y-plane with base at z = 1 and 
// tip at z = -1 to the scene. The mantle will be approximated by 
// nseg segments. The cone can be scaled by an arbitrary 
// transformation matrix P.
// Optionally a color (precisely a pointer to ColorB) can be given to set the
// color of the surface facets (defaults to NULL).
//
{
    int i,j;
    double theta = 0, dtheta = 2*M_PI/nseg;
    
    Vertex& tip  = scene.AddVertex( P*Vertex(0,0,-1) );
    Facet&  base = scene.AddFacet(nseg);
    base(nseg-1) = &scene.AddVertex( P*Vertex(1,0,1) );
    if (color) {
        base.SetColor(*color);
	base[nseg-1].SetColor(*color);
	tip.SetColor(*color);
    }
    for (i = 0, j = nseg-1; i < nseg; j = i++) { 
	theta += dtheta;
	if (i != nseg-1) 
	  base(i) = &scene.AddVertex( P*Vertex(cos(theta),sin(theta),1) );
	Facet& mantle = scene.AddFacet(3);
	mantle(2) = base(j);
	mantle(1) = base(i);
	mantle(0) = &tip;
	if (color) {
	    mantle.SetColor(*color);
	    base[i].SetColor(*color);
	}
    }
}
void MpIcosahedron (Scene &scene, const Trafo &P, const ColorB* color)
{
  const short faces[20][3] = {
    {1, 3, 2}, {1, 4, 3}, {1, 5, 4}, {1, 6, 5},
    {1, 2, 6}, {2, 3, 7}, {3, 4, 8}, {4, 5, 9}, 
    {5, 6, 10}, {6, 2, 11}, {7, 3, 8}, {8, 4, 9}, 
    {9, 5, 10}, {10, 6, 11}, {11, 2, 7}, {7, 8, 12}, 
    {8, 9, 12}, {9, 10, 12}, {10, 11, 12}, {11, 7, 12}};
  const float g = 0.5*(1+sqrt(5.0)), g1 = g-1, p = 0.52573111211913360602567f;
  const float edges[12][3] = {{     0,  0,  g1/p },  {   2*p,  0,     p }, 
			      {  g1*p,  1,     p },  {  -g*p, g1,     p }, 
			      {  -g*p,-g1,     p },  {  g1*p, -1,     p }, 
			      {   g*p, g1,    -p },  { -g1*p,  1,    -p }, 
			      {  -2*p,  0,    -p },  { -g1*p, -1,    -p }, 
			      {   g*p,-g1,    -p },  {     0,  0, -g1/p }};   
  Vertex *v[12];
  int i;
  for (i = 0; i < 12; i++) {
    v[i] = &scene.AddVertex( P * Vertex(edges[i]) );
    if (color) v[i]->SetColor(*color);
  }
  for (i = 0; i < 20; i++) {
    Facet &f = scene.AddFacet(3);
    for (int j = 0; j < 3; j++)
      f(j) = v[faces[i][2-j]-1];
    if (color) f.SetColor(*color);
  }
}
示例#3
0
void stellate (Scene &body, float height)
//
//  Adds starlike jags to every facet of the body. The tip 
//  of a jag is placed in the given height over the center 
//  of the facet.
//
{
    float nx,ny,nz,nk,nn,cx,cy,cz,h;
    Vertex* tip;
    Facet* f;
    int i,j,n;

    Scene stella;
    
    for (f = body.TheFacets(); f; f = f->NextFacet() ) {

	// calculate the normal form and the center of the facet
	f->Normal(nx,ny,nz,nk);
	f->Center(cx,cy,cz);

	// normalization of the normal vector to unit length
	nn = hypot(nx,ny,nz);

	// check if facet is degenerate
	if (nn == 0) continue;

	// add the tip vertex of the jag
	h = height / nn;
	tip = &stella.AddVertex( cx+h*nx, cy+h*ny, cz+h*nz );
	
	// add three-sided facets for each side of the jag
	n = f->GetNumVertices();
	for (i = 0, j = n-1; i < n; j = i++) {
	    Facet& s = stella.AddFacet(3);
	    s(0) = &stella.AddVertex( *(*f)(j) );
	    s(1) = &stella.AddVertex( *(*f)(i) );
	    s(2) = tip;
	}
    }
    
    // now clear the original
    body.Remove();
    
    // and add the stellated body instead (duplicate vertices are now removed)
    body.AddScene(stella,Identity);
}
void MpOctahedron (Scene &scene, const Trafo &P, const ColorB* color)
{
  const short faces[8][3] = {{1, 2, 3}, {1, 3, 5}, {1, 5, 6}, {1, 6, 2},
			     {2, 6, 4}, {2, 4, 3}, {4, 6, 5}, {3, 4, 5}};
  const float t = sqrt(2.0);
  const float edges[6][3] = {{0, 0,  t}, { t, 0, 0}, {0,  t, 0},
			     {0, 0, -t}, {-t, 0, 0}, {0, -t, 0}};
  Vertex *v[6];
  int i;
  for (i = 0; i < 6; i++) {
    v[i] = &scene.AddVertex( P * Vertex(edges[i]) );
    if (color) v[i]->SetColor(*color);
  }
  for (i = 0; i < 8; i++) {
    Facet &f = scene.AddFacet(3);
    for (int j = 0; j < 3; j++)
      f(j) = v[faces[i][j]-1];
    if (color) f.SetColor(*color);
  }
}
示例#5
0
void MpCube (Scene &scene, const Trafo &P, const ColorB* color)
{
    const float edge[8][3] = {
        { 1, 1, 1},
        { 1,-1, 1},
        { 1,-1,-1},
        { 1, 1,-1},
        {-1, 1, 1},
        {-1,-1, 1},
        {-1,-1,-1},
        {-1, 1,-1}
    };

    const signed char face[6][4] = {
        { 0, 1, 2, 3},
        { 0, 3, 7, 4},
        { 0, 4, 5, 1},
        { 2, 6, 7, 3},
        { 1, 5, 6, 2},
        { 4, 7, 6, 5}
    };

    Vertex* v[8];
    int i;
    // create 8 new vertices in this scene transforming them using P
    for (i = 0; i < 8; i++) {
        v[i] = &scene.AddVertex( P * Vertex(edge[i]) );
        if (color) v[i]->SetColor(*color);
    }

    // create 6 new facets in this scene
    for (i = 0; i < 6; i++) {
        // add a new 4-sided facet to this scene
        Facet &f = scene.AddFacet(4);
        // link the edges in this facet to the corresponding vertices
        for (int j = 0; j < 4; j++)
            f(j) = v[face[i][j]];
        // optionally set color
        if (color) f.SetColor(*color);
    }
}
示例#6
0
void Scene::Polygon (short n, float *x, float *y, float *z,
		     long color, short mode)
{
    // check for valid range of vertices
    if (n < 3 || n > MaxVertices) 
      Matpack.Error("Scene::Polygon: number of vertices (%d) not within 3..%d",
		    n,MaxVertices);
 
    Scene scn;                      // local scene copying the original settings
    scn.CopySettingsFrom(*this);
    Facet& f = scn.AddFacet(n);     // add one facet to our local scene
    for (int i = 0; i < n; i++) f(i) = &scn.AddVertex(x[i],y[i],z[i]);
    scn.ClipBoxScene();             // clip at box
    scn.ObserveFacets();            // do observer transformation
    scn.ClipViewScene();            // clip at viewport
    scn.ProjectFacets();            // do perspective projection
    Facet* cf;                      // find the clipped facet
    for (cf = scn.facets; cf && cf->clipped; cf = cf->next);
    if ( cf ) {                     // something left after clipping ?
	for (int i = 0; i < n; i++) // copy projected vertices to polygon array
	    pix[i] = (*cf)[i].p;
	Polygon(n,pix,color,mode);  // draw the facet within the original scene 
    }
}
int MpWarpMatrixToSphere (Scene& S,
                          Matrix& H,
                          Vector& Pol, Vector& Azm,
                          double r,
                          const Trafo& T,
                          int facet_culling,
                          bool periodic,
                          bool south_pole_cap,
                          double h_south,
                          bool north_pole_cap,
                          double h_north,
                          const ColorMap& cmap,
                          double cmin, double cmax,
                          int PolStride, int AzmStride)
{
  int a,p,ncmap = 0;
  double x,y,z,pol,hr,sp,cp;
  double dz,scale = 0.0;
  bool usecolormap;

  int p1 = H.Rlo(), p2 = H.Rhi(), 
      a1 = H.Clo(), a2 = H.Chi();

  // check matrix and vector dimensions
  if (p1 != Pol.Lo() || p2 != Pol.Hi() ||
      a1 != Azm.Lo() || a2 != Azm.Hi())
    return 1;

  // check edge line stride values
  if (PolStride <= 0 || AzmStride <= 0) return 4;

  // evaluate facet culling flag
  int addFront = (facet_culling == Scene::Front) || (facet_culling == false),
      addBack  = (facet_culling == Scene::Back)  || (facet_culling == false);

  // number of facets in polar and azimuthal direction
  int np = p2-p1+1,
      na = a2-a1+1;

  // nothing that can be drawn
  if (np < 2 || na < 2) return 3;
    
  // pointer to vertices in two consecutive slices
  Vertex **top,**bot=0,**act;

  // allocate auxilliary storage
  if ( !(top = new Vertex*[na]) || !(bot = new Vertex*[na]) )
    Matpack.Error("WarpMatrixToSphere: vector allocation failure");
 
  // check if a colormap should be used
  if (cmap) { 
    usecolormap = true;
    dz = cmax-cmin; 
    ncmap = cmap.Size()-1;
    scale = (dz == 0.0) ? 0 : ncmap/dz;
  } else
    usecolormap = false;
        
  // Precompute sines and cosines of the azimuthal angles for the
  // sake of high performance
  Vector s,c;
  s = Sin(Azm);
  c = Cos(Azm);

  // loop through latitudes (polar angle)
  for ( p = p1, act = top; p <= p2; p++ ) {

    pol = Pol(p);
    sp  = sin(pol);
    cp  = cos(pol);

    // loop through longitudes (azimuthal angle)
    for ( a = a1; a <= a2; a++ ) {

      // warp transformation to sphere
      hr  = H(p,a) + r;
      x =  hr * cp * s(a);
      y = -hr * cp * c(a);
      z =  hr * sp;

      // add vertices to scene storing a pointer to it
      // (and apply the global transformation)
      act[a-a1] = &S.AddVertex( T * Vertex((float)x,(float)z,(float)y) );  

      // set the vertex color
      if (usecolormap) {
        int cen = int((H(p,a)-cmin)*scale);
	MpForceRange(cen,0,ncmap);
        act[a-a1]->SetColor(cmap[cen]);
      }
    }

    // first slice or last slice - add triangles to create pole caps
    if ( (south_pole_cap && p == p1) || (north_pole_cap && p == p2) ) { 

      int addF = false,
          addB = false;
      double h = 0.0;
      if (p == p1 && south_pole_cap) {
        addF = addBack;
        addB = addFront;
        h =  -(r + h_south);
      } else if (p == p2 && north_pole_cap) {
        addF = addFront;
        addB = addBack;
        h = r + h_north;
      }
      
      // add vertices to scene storing a pointer to it
      // (and apply the global transformation)
      Vertex* v = &S.AddVertex(T * Vertex((float)0,(float)h,(float)0) );
      
      // set the vertex color
      if (usecolormap) {
        int cen = int((h-cmin)*scale);	
	MpForceRange(cen,0,ncmap);
        v->SetColor(cmap[cen]);
      }
      
      for (a = 0; a < na-1; a++) {
        
        // add with reverse orientation
        if (addB) {
          Facet &f = S.AddFacet(3);
          f(0) = v;
          f(1) = act[a];
          f(2) = act[a+1];
          
          SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride,true);
          
          // set color of facet according to colormap
          if (usecolormap) {
            int cen = int((H(p,a+a1)-cmin)*scale);	
	    MpForceRange(cen,0,ncmap);
            f.SetFrontColor(cmap[cen]);
            f.SetBackColor(cmap[cen]);
          }
        }
        
        // add with normal orientation
        if (addF) {
          Facet &f = S.AddFacet(3);
          f(2) = act[a];
          f(1) = act[a+1];
          f(0) = v;
          
          SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride);
          
          // set color of facet according to colormap
          if (usecolormap) {
            int cen = int((H(p,a+a1)-cmin)*scale);
	    MpForceRange(cen,0,ncmap);
            f.SetFrontColor(cmap[cen]);
            f.SetBackColor(cmap[cen]);
          }
        }
      }
      
      // close sphere periodically in azimuthal direction
      if (periodic) {
        
        // add with opposite orientation
        if (addB) {
          Facet &f = S.AddFacet(3);
          f(0) = v;
          f(1) = act[na-1];
          f(2) = act[0];
          
          SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride,true);
          
          // set color of facet according to colormap
          if (usecolormap) {
            int cen = int((H(p,a1)-cmin)*scale);
	    MpForceRange(cen,0,ncmap);
            f.SetFrontColor(cmap[cen]);
            f.SetBackColor(cmap[cen]);
          }
        }
        
        // add with normal orientation
        if (addF) {
          Facet &f = S.AddFacet(3);
          f(2) = act[na-1];
          f(1) = act[0];
          f(0) = v;
          
          SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride);
          
          // set color of facet according to colormap
          if (usecolormap) {
            int cen = int((H(p,a1)-cmin)*scale);
	    MpForceRange(cen,0,ncmap);
            f.SetFrontColor(cmap[cen]);
            f.SetBackColor(cmap[cen]);
          }
        }
      }
      
    } // if ((south_pole_cap && p == p1) || (north_pole_cap && p == p2)) //

    
    // normal case: add quadrilaterals with top and bottom slices
    if (p != p1) {

      for (a = 0; a < na-1; a++) {

        // add with reverse orientation
        if (addBack) {

          Facet &f = S.AddFacet(4);
          f(0) = top[a];
          f(1) = bot[a];
          f(2) = bot[a+1];
          f(3) = top[a+1];

          SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride,true);

          // set color of facet according to colormap
          if (usecolormap) {
            int cen = int((H(p,a+a1)-cmin)*scale);
	    MpForceRange(cen,0,ncmap);
            f.SetFrontColor(cmap[cen]);
            f.SetBackColor(cmap[cen]);
          }
        }

        // add with normal orientation
        if (addFront) {

          Facet &f = S.AddFacet(4);
          f(3) = top[a];
          f(2) = bot[a];
          f(1) = bot[a+1];
          f(0) = top[a+1];
          
          SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride);

          // set color of facet according to colormap
          if (usecolormap) {
            int cen = int((H(p,a+a1)-cmin)*scale);
	    MpForceRange(cen,0,ncmap);
            f.SetFrontColor(cmap[cen]);
            f.SetBackColor(cmap[cen]);
          }
        }
      }

      // close sphere periodically in azimuthal direction
      if (periodic) {

        // add with reverse orientation
        if (addBack) {
          Facet &f = S.AddFacet(4);
          f(0) = top[na-1];
          f(1) = bot[na-1];
          f(2) = bot[0];
          f(3) = top[0];

          SetEdgeLineVisibility(f,na-1,AzmStride,p-p1,PolStride,true);

          // set color of facet according to colormap
          if (usecolormap) {
            int cen = int((H(p,a1)-cmin)*scale);
	    MpForceRange(cen,0,ncmap);
            f.SetFrontColor(cmap[cen]);
            f.SetBackColor(cmap[cen]);
          }
        }

        // add with normal orientation
        if (addFront) {
          Facet &f = S.AddFacet(4);
          f(3) = top[na-1];
          f(2) = bot[na-1];
          f(1) = bot[0];
          f(0) = top[0];          

          SetEdgeLineVisibility(f,na-1,AzmStride,p-p1,PolStride);

          // set color of facet according to colormap
          if (usecolormap) {
            int cen = int((H(p,a1)-cmin)*scale);
	    MpForceRange(cen,0,ncmap);
            f.SetFrontColor(cmap[cen]);
            f.SetBackColor(cmap[cen]);
          }
        }
      }

    } // if (p == p1) //

    // swap top with bot pointers
    act = bot;
    bot = top;
    top = act;

  } // for ( p = p1, ... ) //

  // remove auxilliary storage
  delete bot;
  delete top;

  // no problems occured
  return 0;
}
示例#8
0
void MpSurfaceBands (Scene& S, const Matrix& z, 
                     int direction, double width, 
                     const ColorMap& cmap, double cmin, double cmax)
{
  Vertex *v0,*v1,*v2,*v3;
  double scale = 0.0;
  bool usecolormap;

  // the width of the bands
  MpForceRange(width,1e-3,1.0);

  // 0.5 is half the mesh unit
  width /= 2;
    
  int ncmap = 0,
    nx = z.Rows(), 
    ny = z.Cols();

  // check arguments
  if ( nx < 0 || ny < 0 ) return; // nothing to draw
   
  // check if a colormap should be used
  if (cmap) { 
    usecolormap = true;
    ncmap = cmap.Size()-1;
    double dz = cmax - cmin; 
    scale = (dz == 0.0) ? 0.0 : ncmap/dz;
  } else
    usecolormap = false;
        
  switch (direction) {

    case RowBandsGrid: 
    case RowBands:
        {

      for ( int y = z.Clo(); y <= z.Chi(); y++ ) { 
        int x = z.Rlo();            
        v0 = &S.AddVertex(y+width,z[x][y],x);
        v1 = &S.AddVertex(y-width,z[x][y],x);
        if (usecolormap) { 
          int c = int((z[x][y]-cmin)*scale);
          if (c > ncmap) 
            c = ncmap;
          else if (c < 0) 
            c = 0;
          const ColorB &col = cmap[c];
          v0->SetColor(col);
          v1->SetColor(col);
        }

        for ( ; x < z.Rhi(); x++) {                 
          // create facet
          Facet &f = S.AddFacet(4);
          v2 = &S.AddVertex(y-width,z[x+1][y],x+1);
          v3 = &S.AddVertex(y+width,z[x+1][y],x+1);
          f(0) = v0;
          f(1) = v1;
          f(2) = v2;
          f(3) = v3;
          v0 = v3;
          v1 = v2;

          // set edge line mask
          if (direction == RowBands)
            if (x == z.Rlo())
              f.SetEdgeLineVisibility(Facet::Individual,0xb); // (1011=0xb)
            else if (x == z.Rhi()-1)
              f.SetEdgeLineVisibility(Facet::Individual,0xe); // (1110=0xe)
            else
              f.SetEdgeLineVisibility(Facet::Individual,0xa); // (1010=0xa)

          // set color of facet according to colormap
          if (usecolormap) { 
            float cx,cy,cz;
            f.Center(cy,cz,cx);
            int c = int((cz-cmin)*scale);
            if (c > ncmap) 
              c = ncmap;
            else if (c < 0) 
              c = 0;
            const ColorB &center = cmap[c];
            f.SetColor(center);
            c = int((z[x+1][y]-cmin)*scale);
            if (c > ncmap) 
              c = ncmap;
            else if (c < 0) 
              c = 0;
            const ColorB &col = cmap[c];
            v2->SetColor(col);
            v3->SetColor(col);
          }
        }
                
      }
      break;
        }

    case ColumnBandsGrid:
    case ColumnBands:
        {
      for ( int x = z.Rlo(); x <= z.Rhi(); x++ ) { 
        int y = z.Clo();
        v1 = &S.AddVertex(y,z[x][y],x-width);
        v2 = &S.AddVertex(y,z[x][y],x+width);
        if (usecolormap) { 
          int c = int((z[x][y]-cmin)*scale);
          const ColorB &col = cmap[c];
          if (c > ncmap) 
            c = ncmap;
          else if (c < 0) 
            c = 0;
          v1->SetColor(col);
          v2->SetColor(col);
        }

        for ( ; y < z.Chi(); y++) {                 
          // create facet
          Facet &f = S.AddFacet(4); 
          v0 = &S.AddVertex(y+1,z[x][y+1],x-width); 
          v3 = &S.AddVertex(y+1,z[x][y+1],x+width);
          f(0) = v0;
          f(1) = v1;
          f(2) = v2;
          f(3) = v3;
          v1 = v0;
          v2 = v3;
                    
          // set edge line mask
          if (direction == ColumnBands)
            if (y == z.Clo())
              f.SetEdgeLineVisibility(Facet::Individual,0x7); // (0111=0x7)
            else if (y == z.Chi()-1)
              f.SetEdgeLineVisibility(Facet::Individual,0xd); // (1101=0xd)
            else
              f.SetEdgeLineVisibility(Facet::Individual,0x5); // (0101=0x5)

          // set color of facet according to colormap
          if (usecolormap) { 
            float cx,cy,cz;
            f.Center(cy,cz,cx);
            int c = int((cz-cmin)*scale);
            if (c > ncmap) 
              c = ncmap;
            else if (c < 0) 
              c = 0;
            const ColorB &center = cmap[c];
            f.SetColor(center);
            c = int((z[x][y+1]-cmin)*scale);
            if (c > ncmap) 
              c = ncmap;
            else if (c < 0) 
              c = 0;
            const ColorB &col = cmap[c];
            v0->SetColor(col);
            v3->SetColor(col);
          }
        }
      }
      break;
        }

    default:
      Matpack.Error("MpSurfaceBands: Illegal value for direction argument");
      break;
  }
}