Function:ns2cvr

From S2PLOT

(Difference between revisions)
Jump to: navigation, search
Revision as of 22:48, 4 December 2007
S2plot admin (Talk | contribs)

← Previous diff
Current revision
S2plot admin (Talk | contribs)

Line 45: Line 45:
== See Also == == See Also ==
<table> <table>
 +<tr><td>[[Function:ns2cvra | ns2crva ]]</td><td>Render volume of objects </td></tr>
<tr><td>[[Function:ds2dvr | ds2dvr ]]</td><td>Draw a volume render object from a dynamic callback </td></tr> <tr><td>[[Function:ds2dvr | ds2dvr ]]</td><td>Draw a volume render object from a dynamic callback </td></tr>
<tr><td>[[Function:ns2cisc | ns2cisc ]]</td><td>Create an isosurface object with a colour function </td></tr> <tr><td>[[Function:ns2cisc | ns2cisc ]]</td><td>Create an isosurface object with a colour function </td></tr>

Current revision

ns2cvr

Create a volume rendering object

Prototype

int ns2cvr(float ***grid, int adim, int bdim, int cdim, int a1, int a2, int b1, int b2, int c1, int c2, 
float *tr, char trans, float datamin, float datamax, float alphamin, float alphamax);

Description

Create a volume rendering object. To display a volume render object you must use the function ds2dvr from within a dynamic callback. See the example below.

The data in grid is a three-dimensional volume indexed by:

grid[0..(adim-1)][0..(bdim-1)][0..(cdim-1)].

The slice of data actually plotted is indexed by [a1..a2][b1..b2][c1..c2].

tr is the transformation matrix which maps indices into the grid onto the x, y and z axes of the 3d world space. The standard (non-rotated, non-skewed) transformation would have tr[2], tr[3], tr[5], tr[7], tr[9] and tr[10] all zero.

The transformation matrix is:

  • x = tr[0] + tr[1] * ia + tr[2] * ib + tr[3] * ic
  • y = tr[4] + tr[5] * ia + tr[6] * ib + tr[7] * ic
  • z = tr[8] + tr[9] * ia + tr[10]* ib + tr[11]* ic

Provide tr = NULL to use the default, unit transformation.

Note that the voxels are pixel centred, so care must be taken with drawing bounding boxes (see the example code below for a solution).

datamin and datamax indicate the range of data values which are mapped to alphamin and alphamax. alpha is the transparency, with 0.0 corresponding to completely transparent (invisible) and 1.0 is opaque. Ordinarily, set datamin and datamax to bracket the signal region of your data, set alphamin to 0.0 and alphamax to something like 0.7.

There are three transparency modes, controlled by the parameter trans:

  • trans = 'o' for opaque regardless of alpha settings;
  • trans = 't' for transparency only; and
  • trans = 's' is transparent allowing absoprtion.

The RGB colour of the isosurface is provided by red, green and blue in the range [0,1].

Set datamin > datamax to request auto-scaling.

Volume rendering works best when the render mode is set to SHADE_FLAT, and only light ambiently. See the example below.

See Also

ns2crva Render volume of objects
ds2dvr Draw a volume render object from a dynamic callback
ns2cisc Create an isosurface object with a colour function
cs2scb Set the callback function; can be null to cancel callback.
s2icm Install various colour maps.
ss2srm Set the rendering mode.
ss2sl Set the entire lighting environment


Code Example

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "s2plot.h"

/* Global variables */
int vid;				/* ID for volume render object */
float tr[12];				/* Transformation matrix */
float ***volume;			/* The data cube */
int N = 5000;				/* Number of data points */
float *x, *y, *z;			/* Arrays for data values */

float ***initVolume(int nx, int ny, int nz)
/* Allocate memory and initialise a data cube */
{
   float ***volume;
   int i, j, k;

   volume = (float ***)malloc(nx * sizeof(float **));
   if (volume == NULL) {
      fprintf(stderr,"Failed to allocate %ld bytes\n",(long)(nx*sizeof(float **)));
      exit(-1);
   }
   for (i=0;i<nx;i++) {
      volume[i] = (float **)malloc(ny * sizeof(float *));
      if (volume[i] == NULL) {
         fprintf(stderr,"Failed to allocate %ld bytes\n",(long)(nx*sizeof(float *)));
         exit(-1);
      }
      for (j=0;j<ny;j++) {
         volume[i][j] = (float *)malloc(nz * sizeof(float));
         if (volume[i][j] == NULL) {
            fprintf(stderr,"Failed to allocate %ld bytes\n",(long)(nx*sizeof(float)));
            exit(-1);
         }
         for (k=0;k<nz;k++) {
            volume[i][j][k] = 0.0;		/* Initialise */
         }
      }
   }

   return volume;
}

void cb(double *t, int *kc)
/* A dynamic callback */
{
   ds2dvr(vid, 1);			/* Draw the volume render object */
   if ((*kc % 2) == 1)
      s2pt(N, x, y, z, 1);		/* Plot the points on <space> press */
}


int main(int argc, char *argv[])
{
   int i; 					/* Loop variable */
   int nx = 32, ny = 32, nz = 32;		/* Dimensions of data cube */ 
   float dmin, dmax, amin, amax;		/* Min/max values */
   char trans;					/* Transparency mode */
   float x1 = -1.0, x2 = +1.0;			/* Data range along axes */
   float y1 = -1.0, y2 = +1.0;
   float z1 = -1.0, z2 = +1.0;
   int vi, vj, vk;				/* Temporary variables */
   float dx, dy, dz;				/* Temporary variables */
   COLOUR amb = {0.8, 0.8, 0.8};		/* Ambient light */

   srand48((long)time(NULL));			/* Seed random numbers */

   volume = initVolume(nx, ny, nz); 		/* Allocate memory */  

   for (i=0;i<12;i++) {				/* Set-up transfrom matrix */
      tr[i] = 0.0;
   }
   tr[ 0]  = x1; 				/* Mapping from data cube */
   tr[ 1]  = (x2-x1)/(float)(nx-1.0);		/* to physical coordinates */
   tr[ 4]  = y1; 
   tr[ 6]  = (y2-y1)/(float)(ny-1.0);
   tr[ 8]  = z1; 
   tr[11]  = (z2-z1)/(float)(nz-1.0);

   dmin = 0.0;			/* Mininum data value in volume to plot */
   dmax = 2.0;			/* Maximum data value in volume to plot */
   amin = 0.0;			/* Minimum alpha channel value */
   amax = 0.8;			/* Maximum alpha channel value */
   trans = 't';			/* Transparency type */

   dx = tr[1]*0.5;		/* Offsets for window - voxels are pixel */
   dy = tr[6]*0.5;		/*  centred */
   dz = tr[11]*0.5;

   s2opend("/S2MONO",argc,argv);			/* Open the display */
   s2swin(x1-dx,x2+dx, y1-dy,y2+dy, z1-dz,z2+dz);	/* Set window coords */
   s2box("BCDE",0,0,"BCDE",0,0,"BCDE",0,0);		/* Draw coord box */

   x = (float *)calloc(N, sizeof(float));
   y = (float *)calloc(N, sizeof(float));
   z = (float *)calloc(N, sizeof(float));

   for (i=0;i<N;i++) {			/* Create N random (x,y,z) values */
      vi = (int)(drand48()*(nx));
      vj = (int)(drand48()*(ny));
      vk = (int)(drand48()*(nz));
      x[i] = vi *  tr[1] + tr[0];
      y[i] = vj *  tr[6] + tr[4];
      z[i] = vk * tr[11] + tr[8];


      volume[vi][vj][vk]+=1.0-drand48()*drand48();	
					/* Give a value to volume */
   }
 
   s2scir(1000,2000);			/* Set colour range */
   s2icm("mgreen",1000,2000);		/* Install colour map */
   vid = ns2cvr(volume, nx, ny, nz, 0, nx-1, 0, ny-1, 0, nz-1, 
		tr, trans, dmin, dmax, amin, amax);
					/* Create the volume render object */

   cs2scb(cb);				/* Install a dynamic callback */

   fprintf(stderr,"Press <space> to toggle showing data points\n");

   ss2srm(SHADE_FLAT);			/* Set shading type to FLAT */
   ss2sl(amb, 0, NULL, NULL, 0);	/* Ambient lighting only */

   s2show(1);				/* Open the s2plot window */

   return 1;
}

Back to S2PLOT function list.


Personal tools