/* -*-C-*- ******************************************************************************* * * File: vol.c * RCS: $Header: vol.c,v 1.1 92/03/03 11:12:12 hstroyan Exp $ * Description: CRX24 Volume rendering module for AVS * Author: Howard Stroyan * Created: * Modified: * Language: C * Package: N/A * Status: Experimental (Do Not Distribute) * * (C) Copyright 1992, Hewlett-Packard, all rights reserved. * ******************************************************************************* */ #include #include #include #include #include #include #include #include #include #include #include #include int gfd; unsigned char *data; int display_volume_init(); int dbuf=0; unsigned int num_points_per_line; unsigned int num_lines_per_slice; unsigned int num_slices; int redraw = 0; display_volume() { int x_scale, y_scale, z_scale; int db, auto_fill, text; /* Set module name */ AVSset_module_name("display ARGB vol 2", MODULE_RENDER); /* Create input ports */ AVScreate_input_port("volume_data", "field 3D 4-vector byte uniform", REQUIRED); AVScreate_input_port("xform", "field 2D scalar float", REQUIRED); /* Create parameters */ db = AVSadd_parameter("Double Buffer", "boolean", 0, 0, 1); auto_fill = AVSadd_parameter("Auto Fill", "boolean", 0, 0, 1); text = AVSadd_parameter("Performance Status", "string_block", " ", " ", " "); AVSconnect_widget(text, "textblock"); AVSadd_parameter_prop(text, "width", "integer", 4); x_scale = AVSadd_float_parameter("X Scale", 1.0, 0.0, 4.0); y_scale = AVSadd_float_parameter("Y Scale", 1.0, 0.0, 4.0); z_scale = AVSadd_float_parameter("Z Scale", 1.0, 0.0, 4.0); AVSconnect_widget(db, "toggle"); AVSconnect_widget(auto_fill, "toggle"); AVSconnect_widget(x_scale, "dial"); AVSconnect_widget(y_scale, "dial"); AVSconnect_widget(z_scale, "dial"); } void expose(widget, client_data, call_data) Widget widget; caddr_t client_data; XmDrawingAreaCallbackStruct *call_data; { redraw = TRUE; } void resize(widget, client_data, call_data) Widget widget; caddr_t client_data; XmDrawingAreaCallbackStruct *call_data; { if (gfd) vdc_extent(gfd, -1.0,-1.0,-1.0,1.0,1.0,1.0); } /*************************************************************************** * display_volume_compute * ***************************************************************************/ main(argc,argv) int argc; char *argv[]; { float *hue, *sat, *lum, *alpha; int a; float x_start, x_end; float y_start, y_end; float z_start, z_end; float max_dim; gescape_arg arg1, arg2; char *text; char message[256]; struct tms start_buffer, end_buffer; unsigned int total_num_points; long start_ticks, end_ticks; float total_time; AVSfield_char *data_field; AVSfield_float *transform; int db, auto_fill; float *x_scale, *y_scale, *z_scale; XtAppContext app_context; /* application context */ Widget toplevel, sb; Arg arg[15]; int n; int mask; static String fallbacks[] = { "*Starbase*width: 256", "*Starbase*height: 256", NULL }; AVScorout_init(argc,argv,display_volume); AVScorout_set_sync(1); toplevel = XtAppInitialize(&app_context, "DRawingArea", NULL, 0, &argc, argv, fallbacks, NULL, 0); n = 0; XtSetArg(arg[n], XgNshadeMode, XgCMAP_FULL); n++; sb = XtCreateManagedWidget("Starbase", xgStarbaseWidgetClass, toplevel, arg, n); XtAddCallback(sb, XmNexposeCallback, expose, NULL); XtAddCallback(sb, XmNresizeCallback, resize, NULL); XtRealizeWidget(toplevel); { Arg arg[10]; int n; /* Find the Starbase file descriptor. */ n = 0; XtSetArg(arg[n], XgNfildes, &gfd); n++; XtGetValues(sb, arg, n); } display_volume_init(); while(1) { XtInputMask local_mask; mask = COROUT_WAIT; AVScorout_X_wait(XtDisplay(toplevel),NULL, &mask); if (local_mask = XtAppPending(app_context)) { XtAppProcessEvent(app_context, local_mask); } AVScorout_input( &data_field, &transform, &db, &auto_fill, &text, &x_scale, &y_scale, &z_scale); /* TRANSFER DATA FIELD TO GESCAPE FORMAT */ if (AVSinput_changed("volume_data", 0) != 0) { redraw = TRUE; data = data_field->data; num_points_per_line = data_field->dimensions[0]; num_lines_per_slice = data_field->dimensions[1]; num_slices = data_field->dimensions[2]; max_dim = num_points_per_line; if (num_lines_per_slice > max_dim) max_dim = num_lines_per_slice; if (num_slices > max_dim) max_dim = num_slices; max_dim = 1.0 / (float)max_dim; } total_num_points = num_points_per_line * num_lines_per_slice * num_slices; /* LOAD NEW VIEWING TRANSFORMATION TO STARBASE */ if (AVSinput_changed("xform", 0) != 0) { static float invert_z[4][4] = {{ 1.0, 0.0, 0.0, 0.0}, { 0.0, 1.0, 0.0, 0.0}, { 0.0, 0.0,-1.0, 0.0}, { 0.0, 0.0, 0.0, 1.0}}; redraw = TRUE; replace_matrix3d(gfd, transform->data); concat_transformation3d(gfd, invert_z, POST, REPLACE); } /* CHECK DOUBLE BUFFER STATE */ if (AVSparameter_changed("Double Buffer") != 0) { redraw = TRUE; if (db) { double_buffer(gfd,TRUE|INIT,24); } else { double_buffer(gfd,INIT,24); } } if ((AVSparameter_changed("Auto Fill") != 0) | (AVSparameter_changed("X Scale") != 0) | (AVSparameter_changed("Y Scale") != 0) | (AVSparameter_changed("Z Scale") != 0)) redraw = TRUE; if (redraw) { x_start = (float)-0.8 * *x_scale * (float)num_points_per_line * max_dim; y_start = (float)-0.8 * *y_scale * (float)num_lines_per_slice * max_dim; z_start = (float)-0.8 * *z_scale * (float)num_slices * max_dim; x_end = (float)0.8 * *x_scale * (float)num_points_per_line * max_dim; y_end = (float)0.8 * *y_scale * (float)num_lines_per_slice * max_dim; z_end = (float)0.8 * *z_scale * (float)num_slices * max_dim; arg1.f[0] = x_start; /* START OF FIRST SCANLINE, IN THE FIRST SLICE */ arg1.f[1] = y_start; arg1.f[2] = z_start; arg1.f[3] = x_end; /* END OF FIRST SCANLINE, IN THE FIRST SLICE */ arg1.f[4] = y_start; arg1.f[5] = z_start; arg1.f[6] = x_start; /* START OF LAST SCANLINE, IN THE FIRST SLICE */ arg1.f[7] = y_end; arg1.f[8] = z_start; arg1.f[9] = x_start; /* START OF FIRST SCANLINE, IN THE LAST SLICE */ arg1.f[10] = y_start; arg1.f[11] = z_end; arg1.i[12] = num_points_per_line; arg1.i[13] = num_lines_per_slice; /* not a very accurate description */ arg1.i[14] = num_slices; arg1.i[15] = 0; arg1.i[16] = 0; arg1.i[17] = 0; arg1.i[18] = 0; if (auto_fill) arg1.i[18] |= AUTO_FILL_VOXEL; arg1.i[19] = data; arg1.i[20] = 0; clear_view_surface(gfd); start_ticks = times(&start_buffer); gescape (gfd, CUBIC_POLYPOINT, &arg1, &arg2); end_ticks = times(&end_buffer); total_time = (float) (end_ticks - start_ticks) / (float) HZ; sprintf(message, "Performance Statistics\n %d voxels rendered\n %6.3f seconds rendering time\n %6.3f Million Voxels/second",total_num_points,total_time,total_num_points / total_time / 1e6); AVSmodify_parameter("Performance Status",AVS_VALUE, message," "," "); redraw = 0; if (db) dbuffer_switch(gfd,dbuf++); } AVSmodule_status("done",100); } } int display_volume_init() { float empty_matrix[4][4]; shade_mode(gfd, INIT | CMAP_FULL, 0); depth_indicator(gfd, 0, 0); clip_indicator(gfd, CLIP_OFF); hidden_surface(gfd, 0, 0); push_matrix3d(gfd, empty_matrix); vdc_extent(gfd, -1.0,-1.0,-1.0,1.0,1.0,1.0); } hsl_to_rgb(hue,saturation,luminosity,red,green,blue) float hue, saturation, luminosity; float *red, *green, *blue; { float frac, lx, ly, lz; hue = 6 * hue; frac = hue - (int) hue; lx = luminosity * (1 - saturation); ly = luminosity * (1 - saturation * frac); lz = luminosity * (1 - saturation * (1-frac)); switch ((int) hue) { case 0: case 6: *red = luminosity; *green = lz; *blue = lx; break; case 1: *red = ly; *green = luminosity; *blue = lx; break; case 2: *red = lx; *green = luminosity; *blue = lz; break; case 3: *red = lx; *green = ly; *blue = luminosity; break; case 4: *red = lz; *green = lx; *blue = luminosity; break; case 5: *red = luminosity; *green = lx; *blue = ly; break; } }