Angus Dorbie (angus++at++division.co.uk)
Tue, 30 May 1995 11:42:29 +0100
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
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:51:32 PDT