Re: NURBS

New Message Reply Date view Thread view Subject view Author view

Angus Dorbie (angus++at++division.co.uk)
Tue, 30 May 1995 11:42:29 +0100


> What about glsphere primtype for geosets?
> That should be easy enough to have it now..

Here's some code to generate geosets with a number of spheres with different
origins & radii.
Each sphere is generated as a set of nonindexed tristrips. The polygon
mesh isn't ideal but it's what was required at the time.

The dicing values can be changed and data is cached for the last dicing used.

The structure g holds an array of sphere coordinates & radii in g->vertdata
+ possible colour information. The number of spheres is held in g->numvert
and the size of information for an individual sphere is held in g->vertsize
g->*_inc holds the relative offset of each piece of information in a vertex
and depends upon how you build your array of spheres.
g->vertype indicates what information is stored for each sphere.
g->Long & g->Lat hold the longitudinal & latitudinal dicing values.
g->Pgeoset is the performer geoset where the spheres are being created.
g->transparent is TRUE when transparency is implied by colour information
for the spheres.

static void _MakeSpheres(_gset_holder *g)
{
  int i, j, pos, post, x;
  float angleLat, angleLong, incLat, incLong, LatSin, LatCos, LongSin, LongCos;
  float _xp, _yp, _zp, _rad;
  /* triangle connections */
  int first_sphere;
  static pfVec3 *Template = NULL;
  static int Last_Long = 0;
  static int Last_Lat = 0;

  /* dicing values rounded to two */
  int LONG = g->Long;
  int LAT = g->Lat;
  if(LONG < 3) /* set a reasonable minimum */
    LONG = 3;
  if(LAT < 2) /* set a reasonable minimum */
    LAT = 2;
  if(LONG != Last_Long || LAT != Last_Lat)
    first_sphere = TRUE;
  else
    first_sphere = FALSE;
  Last_Long = LONG;
  Last_Lat = LAT;

  if(first_sphere)
  {
    if(Template)
      pfFree(Template);
    first_sphere = FALSE;
    Template = (pfVec3 *)pfMalloc(sizeof(pfVec3)*LONG*LAT*2, NULL);
    /* generate surface normals used by all spheres */
    /* end points */
    Template[0][0] = 0.0f;
    Template[0][1] = 1.0f;
    Template[0][2] = 0.0f;
    Template[LONG*(LAT-1)+1][0] = 0.0f;
    Template[LONG*(LAT-1)+1][1] = -1.0f;
    Template[LONG*(LAT-1)+1][2] = 0.0f;
    angleLat = 90.0f;
    incLat = 180.0f / LAT;
    incLong = 360.0f / LONG;
    for(i=0, angleLat = 90.0f - incLat; i < (LAT-1); i++, angleLat -= incLat)
    {
      pfSinCos(angleLat, &LatSin, &LatCos);
      for(j=0, angleLong = 0.0f; j < LONG; j++, angleLong += incLong)
      {
        pos = i*LONG+j+1;
        pfSinCos(angleLong, &LongSin, &LongCos);
        Template[pos][0] = LongSin * LatCos;
        Template[pos][1] = LatSin;
        Template[pos][2] = LongCos * LatCos;
      }
    }
  }
  /* allocate space for saved sphere coordinates */
  g->sphvert = (float *)pfMalloc(sizeof(float)*g->numvert*4, NULL);
  /* allocate space for normals */
  g->Pnorms = (pfVec3 *)pfMalloc(sizeof(pfVec3)*g->numvert*LONG*LAT*2,
                        pfGetSharedArena());
  /* space for the sphere surface coordinates */
  g->Pcoords = (pfVec3 *)pfMalloc(sizeof(pfVec3)*g->numvert*LONG*LAT*2,
                        pfGetSharedArena());
  /* space for the tristrip lengths */
  g->Plengths = (long *)pfMalloc(sizeof(long)*g->numvert*LONG,
                        pfGetSharedArena());
  /* do colours */
  if(g->vertype & dpl_vertex_rgba || g->vertype & dpl_vertex_luminance)
    g->Pcolours = (pfVec4 *)pfMalloc(sizeof(pfVec4)*g->numvert*LONG,
                        pfGetSharedArena());

  /* copy coordinate and normal information for each sphere */
  /* normals don't change, coordinate information is scaled & translated */
  /* start position of sphere vertices & length position counters */
  pos = post = 0;

  for(x=0; x < g->numvert; x++) /* for each sphere */
  {
    /* read relevant sphere information */
    _xp = *(g->vertdata + g->vertsize*x + g->coord_inc);
    _yp = *(g->vertdata + g->vertsize*x + 1 + g->coord_inc);
    _zp = *(g->vertdata + g->vertsize*x + 2 + g->coord_inc);
    if(g->vertype & dpl_vertex_radius)
      _rad = *(g->vertdata + g->vertsize*x + g->rad_inc);
    else
      _rad = 1.0f;

    /* store sphere sizes & positions */
    *(g->sphvert + (x*4)) = _xp;
    *(g->sphvert + (x*4 + 1)) = _yp;
    *(g->sphvert + (x*4 + 2)) = _zp;
    *(g->sphvert + (x*4 + 3)) = _rad;

    /* tristrip in segments */
    for(j=0; j < LONG; j++)
    {
      /* add one tristrip (nonindexed) */
      g->Pcoords[pos][0] = _xp + _rad * Template[0][0];
      g->Pcoords[pos][1] = _yp + _rad * Template[0][1];
      g->Pcoords[pos][2] = _zp + _rad * Template[0][2];
      g->Pnorms[pos][0] = Template[0][0];
      g->Pnorms[pos][1] = Template[0][1];
      g->Pnorms[pos][2] = Template[0][2];
      pos ++;
      for(i=0; i < (LAT-1); i++)
      {
        g->Pcoords[pos][0] = _xp + _rad * Template[i*LONG+j+1][0];
        g->Pcoords[pos][1] = _yp + _rad * Template[i*LONG+j+1][1];
        g->Pcoords[pos][2] = _zp + _rad * Template[i*LONG+j+1][2];
        g->Pnorms[pos][0] = Template[i*LONG+j+1][0];
        g->Pnorms[pos][1] = Template[i*LONG+j+1][1];
        g->Pnorms[pos][2] = Template[i*LONG+j+1][2];
        pos ++;
        if(j == LONG-1)
        {
          g->Pcoords[pos][0] = _xp + _rad * Template[i*LONG+1][0];
          g->Pcoords[pos][1] = _yp + _rad * Template[i*LONG+1][1];
          g->Pcoords[pos][2] = _zp + _rad * Template[i*LONG+1][2];
          g->Pnorms[pos][0] = Template[i*LONG+1][0];
          g->Pnorms[pos][1] = Template[i*LONG+1][1];
          g->Pnorms[pos][2] = Template[i*LONG+1][2];
        }
        else
        {
          g->Pcoords[pos][0] = _xp + _rad * Template[i*LONG+j+2][0];
          g->Pcoords[pos][1] = _yp + _rad * Template[i*LONG+j+2][1];
          g->Pcoords[pos][2] = _zp + _rad * Template[i*LONG+j+2][2];
          g->Pnorms[pos][0] = Template[i*LONG+j+2][0];
          g->Pnorms[pos][1] = Template[i*LONG+j+2][1];
          g->Pnorms[pos][2] = Template[i*LONG+j+2][2];
        }
        pos ++;
      }
      g->Pcoords[pos][0] = _xp + _rad * Template[LONG*(LAT-1)+1][0];
      g->Pcoords[pos][1] = _yp + _rad * Template[LONG*(LAT-1)+1][1];
      g->Pcoords[pos][2] = _zp + _rad * Template[LONG*(LAT-1)+1][2];
      g->Pnorms[pos][0] = Template[LONG*(LAT-1)+1][0];
      g->Pnorms[pos][1] = Template[LONG*(LAT-1)+1][1];
      g->Pnorms[pos][2] = Template[LONG*(LAT-1)+1][2];
      pos ++;

      /* do colours */
      if(g->vertype & dpl_vertex_rgba)
      {
        g->Pcolours[post][0] = *(g->vertdata+ g->vertsize*x + g->rgba_inc);
        g->Pcolours[post][1] = *(g->vertdata+ g->vertsize*x + 1 + g->rgba_inc);
        g->Pcolours[post][2] = *(g->vertdata+ g->vertsize*x + 2 + g->rgba_inc);
        g->Pcolours[post][3] = *(g->vertdata+ g->vertsize*x +3+ g->rgba_inc);
        if( .997 > g->Pcolours[post][3] )
          g->transparent = TRUE;
      }
      else
      if(g->vertype & dpl_vertex_luminance)
      {
        g->Pcolours[post][0] =
        g->Pcolours[post][1] =
        g->Pcolours[post][2] = *(g->vertdata+ g->vertsize*x + g->lum_inc);
        g->Pcolours[post][3] = *(g->vertdata+ g->vertsize*x +1+ g->lum_inc);
        if( .997 > g->Pcolours[post][3] )
            g->transparent = TRUE;
      }

      g->Plengths[post] = LAT*2;
      post++;

    }
  }

  /* compose sphere of triangular strips */
  pfGSetPrimType(g->Pgeoset, PFGS_TRISTRIPS);

  /* do colours (requires appropriate use of materials) */
  if(g->vertype & dpl_vertex_rgba || g->vertype & dpl_vertex_luminance)
    pfGSetAttr(g->Pgeoset, PFGS_COLOR4, PFGS_PER_PRIM, g->Pcolours, NULL);

  /* primitive lengths for each triangle strip */
  pfGSetPrimLengths(g->Pgeoset, g->Plengths);
  pfGSetAttr(g->Pgeoset, PFGS_NORMAL3, PFGS_PER_VERTEX, g->Pnorms, NULL);
  pfGSetAttr(g->Pgeoset, PFGS_COORD3, PFGS_PER_VERTEX, g->Pcoords, NULL);
  /* tristrips per sphere * spheres */
  pfGSetNumPrims(g->Pgeoset, g->numvert*LONG);
}

-- 
 Angus Dorbie                Division Ltd,
 Software Engineer           19 Apex Court,
 Tel: (01454)615554          Woodlands,
 Fax: (01454)615532          Bristol BS12 4JT,
 angus++at++division.co.uk        UK

New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:51:32 PDT

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.