/* render.c */
/*
* Vis5D system for visualizing five dimensional gridded data sets.
* Copyright (C) 1990 - 2000 Bill Hibbard, Johan Kellum, Brian Paul,
* Dave Santek, and Andre Battaiola.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* As a special exception to the terms of the GNU General Public
* License, you are permitted to link Vis5D with (and distribute the
* resulting source and executables) the LUI library (copyright by
* Stellar Computer Inc. and licensed for distribution with Vis5D),
* the McIDAS library, and/or the NetCDF library, where those
* libraries are governed by the terms of their own licenses.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "../config.h"
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "anim.h"
#include "api.h"
#include "box.h"
#include "matrix.h"
#include "globals.h"
#include "graphics.h"
#include "grid.h"
#include "labels.h"
#include "map.h"
#include "memory.h"
#include "misc.h"
#include "proj.h"
#include "queue.h"
#include "sounding.h"
#include "sync.h"
#include "topo.h"
#include "vis5d.h"
#include "volume.h"
#include "v5d.h"
extern int vis5d_verbose;
#define MAX(A,B) ( (A) > (B) ? (A) : (B) )
#define MIN(A,B) ( (A) < (B) ? (A) : (B) )
#define ABS(X) ( (X) < 0.0f ? -(X) : (X) )
#define TICK_SIZE 0.05
#define CLOCK_SEGMENTS 36
#define VERT(Z) (ctx->VerticalSystem==VERT_NONEQUAL_MB ? height_to_pressure(Z) : (Z))
#define VERTPRIME(Z) (dtx->VerticalSystem==VERT_NONEQUAL_MB ? height_to_pressure(Z) : (Z))
/* Vertical spacing between rows of text: (in pixels) */
#define VSPACE 1
/*** float2string *****************************************************
Convert a float into an ascii string.
**********************************************************************/
/* MJK 12.01.98 */
/* old now
void float2string( float f, char *str )
{
if (f==0.0 || fabs(f)<0.01)
strcpy( str, "0.0" );
else if (f>=100.0 || f<=-100.0)
sprintf(str, "%d", (int) f );
else
sprintf(str, "%4.2f", f );
}
*/
/* MJK 12.01.98 */
void float2string (Display_Context dtx, int icoord, float f, char *str)
{
float fmin, fmax, frng;
if (fabs (f) < 0.01) f = 0.0;
if (dtx->CoordFlag) {
switch (icoord) {
case 0:
fmin = 1.0;
fmax = dtx->Nc;
break;
case 1:
fmin = 1.0;
fmax = dtx->Nr;
break;
case 2:
fmin = 1.0;
fmax = dtx->MaxNl;
break;
}
}
else {
switch (icoord) {
case 0:
fmin = dtx->WestBound;
fmax = dtx->EastBound;
break;
case 1:
fmin = dtx->SouthBound;
fmax = dtx->NorthBound;
break;
case 2:
fmin = VERTPRIME(dtx->BottomBound);
fmax = VERTPRIME(dtx->TopBound);
break;
}
}
frng = (fmin < fmax) ? fmax - fmin : fmin - fmax;
if (frng < 500.0)
sprintf (str, "%.2f", f);
else
sprintf (str, "%.0f", f);
}
/*** check_view_side *****************************************************
Determine if the plane of a clockwise series of points faces the camera.
return: -1 plane faces away from the camera
0 plane includes the camera
1 plane faces the camera
**********************************************************************/
int check_view_side (Context ctx, int type, int num)
{
int iside;
float xyz[3][3], xy[3][2], area;
switch (type)
{
/* Need to work on non-vertical slices */
case VSLICE:
xyz[0][0] = ctx->Variable[num]->VSliceRequest->X2;
xyz[0][1] = ctx->Variable[num]->VSliceRequest->Y2;
xyz[0][2] = ctx->dpy_ctx->Zmin;
xyz[1][0] = ctx->Variable[num]->VSliceRequest->X1;
xyz[1][1] = ctx->Variable[num]->VSliceRequest->Y1;
xyz[1][2] = ctx->dpy_ctx->Zmin;
xyz[2][0] = ctx->Variable[num]->VSliceRequest->X1;
xyz[2][1] = ctx->Variable[num]->VSliceRequest->Y1;
xyz[2][2] = ctx->dpy_ctx->Zmax;
break;
default:
return 0;
}
project (&xyz[0][0], &xy[0][0], &xy[0][1]);
project (&xyz[1][0], &xy[1][0], &xy[1][1]);
project (&xyz[2][0], &xy[2][0], &xy[2][1]);
area = ((xy[0][0] - xy[2][0]) * (xy[0][1] + xy[2][1])) +
((xy[1][0] - xy[0][0]) * (xy[1][1] + xy[0][1])) +
((xy[2][0] - xy[1][0]) * (xy[2][1] + xy[1][1]));
iside = (area > 0.0) ? -1 : (area < 0.0) ? 1 : 0;
return iside;
}
int flip_vslice_end_for_end (Context ctx, int time, int var)
{
float x;
x = ctx->Variable[var]->VSliceRequest->R1;
ctx->Variable[var]->VSliceRequest->R1 = ctx->Variable[var]->VSliceRequest->C1;
ctx->Variable[var]->VSliceRequest->C1 = x;
x = ctx->Variable[var]->VSliceRequest->R2;
ctx->Variable[var]->VSliceRequest->R2 = ctx->Variable[var]->VSliceRequest->C2;
ctx->Variable[var]->VSliceRequest->C2 = x;
x = ctx->Variable[var]->VSliceRequest->X1;
ctx->Variable[var]->VSliceRequest->X1 = ctx->Variable[var]->VSliceRequest->X2;
ctx->Variable[var]->VSliceRequest->X2 = x;
x = ctx->Variable[var]->VSliceRequest->Y1;
ctx->Variable[var]->VSliceRequest->Y1 = ctx->Variable[var]->VSliceRequest->Y2;
ctx->Variable[var]->VSliceRequest->Y2 = x;
x = ctx->Variable[var]->VSliceRequest->Lat1;
ctx->Variable[var]->VSliceRequest->Lat1 = ctx->Variable[var]->VSliceRequest->Lat2;
ctx->Variable[var]->VSliceRequest->Lat2 = x;
x = ctx->Variable[var]->VSliceRequest->Lon1;
ctx->Variable[var]->VSliceRequest->Lon1 = ctx->Variable[var]->VSliceRequest->Lon2;
ctx->Variable[var]->VSliceRequest->Lon2 = x;
request_vslice (ctx, time, var, (time == ctx->CurTime));
return 0;
}
/* same code as in uvwwidget.c */
char *return_var_plus_index( char *varname, int index )
{
int yo;
/* WLH 20 Oct 98
char whole[40];
*/
/* WLH 20 Oct 98 */
char* whole;
char num[40];
/* WLH 20 Oct 98 */
whole = (char *) malloc(40);
if (index <0 || varname[0] == 0){
whole[0] = 0;
return whole;
}
for (yo = 0; yo < 17; yo++){
if (varname[yo] == '\0' || varname[yo] == ' '){
yo -=1;
whole[yo+1] = '.';
sprintf(num, "%d\n", index );
if (index > 99 && yo < 15){
whole[yo+2] = num[0];
whole[yo+3] = num[1];
whole[yo+4] = num[2];
whole[yo+5] = '\0';
return whole;
}
else if ( index > 9 && yo < 16){
whole[yo+2] = num[0];
whole[yo+3] = num[1];
whole[yo+4] = '\0';
return whole;
}
else{
whole[yo+2] = num[0];
whole[yo+3] = '\0';
return whole;
}
}
whole[yo] = varname[yo];
}
whole[yo] = '\0';
return whole;
}
/*** plot_string ******************************************************
Plot (draw) a string in 3-D. At this time, only strings of digits,
periods, and dashes are implemented.
Input: f - the string to plot.
startx, y, z - the point in 3-D to start at.
base - vector indicating text baseline.
up - vector indicating upright direction for text.
rjustify - non-zero value indicates right justify the text.
**********************************************************************/
void plot_string( char *str, float startx, float starty, float startz,
float base[], float up[], int rjustify )
{
static float zero[] = { 0,0, 0,.8, .4,.8, .4,0, 0,0 },
one[] = { 0,0, 0,.8 },
two[] = { .4,0, 0,0, 0,.4, .4,.4, .4,.8, 0,.8 },
three[] = { 0,0, .4,0, .4,.4, 0,.4, .4,.4, .4,.8, 0,.8 },
four[] = { 0,.8, 0,.4, .4,.4, .4,.8, .4,0 },
five[] = { 0,0, .4,0, .4,.4, 0,.4, 0,.8, .4,.8 },
six[] = { .4,.8, 0,.8, 0,0, .4,0, .4,.4, 0,.4 },
seven[] = { 0,.7, 0,.8, .4,.8, .4,0 },
eight[] = { 0,0, 0,.8, .4,.8, .4,0, 0,0, 0,.4, .4,.4 },
nine[] = { .4,.4, 0,.4, 0,.8, .4,.8, .4,0 },
dash[] = { 0,.4, .4,.4 },
dot[] = { 0,0, 0,.1, .1,.1, .1,0, 0,0 },
/*MiB 03/2001 Longitudes*/
west[] = {0.,0.8, 0.,0., 0.2,0.4, 0.4,0.0, 0.4,0.8},
east[] = {0.4,0.8, 0.0,0.8, 0.0,0.4, 0.3,0.4, 0.0,0.4, 0.0,0.0, 0.4,0.0},
north[] = {0.,0.0, 0.,0.8, 0.4,0.0, 0.4,0.8},
south[] = {0.0,0.1, 0.1,0.0, 0.3,0.0, 0.4,0.1, 0.4,0.3,
0.0,0.5, 0.0,0.7, 0.1,0.8, 0.3,0.8, 0.4,0.7};
static float *index[16] = { zero, one, two, three, four, five, six,
seven, eight, nine, dash, dot, west, east,
north, south};
static float width[16] = { 0.6, 0.2, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6,
0.6, 0.6, 0.6, 0.3, 0.6, 0.6 , 0.6, 0.6};
static int verts[16] = { 5, 2, 6, 7, 5, 6, 6, 4, 7, 5, 2, 5 ,5, 7, 4, 10};
float *temp, plot[100][3];
float cx, cy, cz;
int i, j, k, len;
cx = startx; cy = starty; cz = startz;
len = strlen(str);
if (rjustify) {
/* draw right justified text */
for (i=len-1; i>=0; i--) {
if (str[i]=='-')
k = 10;
else if (str[i]=='.')
k = 11;
/*MiB*/ else if (str[i]=='W')
k = 12;
else if (str[i]=='E')
k = 13;
else if (str[i]=='N')
k = 14;
else if (str[i]=='S')
/*MiB*/ k = 15;
else if (str[i]>='0' && str[i]<='9')
k = str[i] - '0';
else
continue;
/* calculate position for this char */
cx += width[k]*base[0];
cy += width[k]*base[1];
cz += width[k]*base[2];
/* make the vertex array for this character */
temp = index[k];
for (j=0; j<verts[k]; j++) {
float x, y;
x = *temp++;
y = *temp++;
plot[j][0] = cx - x*base[0] + y*up[0];
plot[j][1] = cy - x*base[1] + y*up[1];
plot[j][2] = cz - x*base[2] + y*up[2];
}
polyline( plot, verts[k] );
}
}
else {
/* draw left justified text */
for (i=0; i<len; i++) {
if (str[i]=='-')
k = 10;
else if (str[i]=='.')
k = 11;
/*MiB*/ else if (str[i]=='W')
k = 12;
else if (str[i]=='N')
k = 14;
else if (str[i]=='S')
k = 15;
else if (str[i]=='E')
/*MiB*/ k = 13;
else if (str[i]>='0' && str[i]<='9')
k = str[i] - '0';
else
continue;
/* make the vertex array for this character */
temp = index[k];
for (j=0; j<verts[k]; j++) {
float x, y;
x = *temp++;
y = *temp++;
plot[j][0] = cx + x*base[0] + y*up[0];
plot[j][1] = cy + x*base[1] + y*up[1];
plot[j][2] = cz + x*base[2] + y*up[2];
}
polyline( plot, verts[k] );
/* calculate position for next char */
cx += width[k]*base[0];
cy += width[k]*base[1];
cz += width[k]*base[2];
}
}
}
int check_for_valid_time( Context ctx, int dtxcurtime)
{
Display_Context dtx;
int dtime, stime, ldtime, lstime;
int ctxcurtime, yo, ctime, spandex;
int ctxdtime, ctxstime;
dtx = ctx->dpy_ctx;
if (dtx->numofctxs == 1){
return 1;
}
if (ctx->NumTimes == 1){
return 1;
}
ctxcurtime =
ldtime = lstime = 0;
for( yo = 0; yo < dtx->numofctxs; yo ++){
spandex = dtx->TimeStep[dtxcurtime].owners[yo];
ctime = dtx->TimeStep[dtxcurtime].ownerstimestep[yo];
vis5d_get_ctx_time_stamp( spandex, ctime, &dtime, &stime);
if (spandex == ctx->context_index){
ctxcurtime = ctime;
ctxdtime = dtime;
ctxstime = stime;
}
else if (dtime > ldtime || (dtime == ldtime && stime > lstime)){
ldtime = dtime;
lstime = stime;
}
}
if (ctxcurtime == 0 && (ctxdtime > ldtime ||
(ctxdtime == ldtime && ctxstime > lstime))){
return 0;
}
else if (ctxcurtime == ctx->NumTimes-1 && (ctxdtime < ldtime ||
(ctxdtime == ldtime && ctxstime < lstime))){
return 0;
}
else{
return 1;
}
}
/*
* Draw the tick mark for a horizontal slice.
* Input: level - grid level
* z - graphics z coord
* height - geographic height coord
*/
static void draw_horizontal_slice_tick( Display_Context dtx, float level,
float z, float height )
{
float v[2][3];
static float base[3] = { 0.035, -0.035, 0.0 };
static float up[3] = { 0.0, 0.0, 0.07 };
char str[1000];
/* vertices for tick mark */
v[0][0] = dtx->Xmax;
v[0][1] = dtx->Ymin;
v[0][2] = z;
v[1][0] = dtx->Xmax + 0.05;
v[1][1] = dtx->Ymin - 0.05;
v[1][2] = z;
polyline( v, 2 );
/* the label */
if (dtx->CoordFlag) {
/* MJK 12.01.98 */
float2string(dtx, 2, level+1.0, str );
}
else {
/* MJK 12.01.98 */
float2string(dtx, 2, VERTPRIME(height), str );
}
plot_string( str, dtx->Xmax+0.07, dtx->Ymin-0.07, z, base,up, 0 );
}
/*
* Draw a tick mark for a vertical slice.
* Input: row, col - position in grid coords
* x, y - position in graphics coords
* lat,lon - position in geographic coords
*/
static void draw_vertical_slice_tick( Display_Context dtx, float row, float col,
float x, float y, float lat, float lon )
{
float v[2][3];
int cc, rr;
/* base and up vectors for drawing 3-D text */
static float b2[3] = { 0.05, 0.0, 0.0 }, u2[3] = { 0.0, 0.05, 0.0 };
static float b3[3] = { -0.05, 0.0, 0.0 }, u3[3] = { 0.0, 0.05, 0.0 };
char str[1000];
cc = (int) (col);
rr = (int) (row);
if (cc <= 0) {
/* draw on top-west edge */
v[0][0] = x;
v[0][1] = y;
v[0][2] = dtx->Zmax;
v[1][0] = x-0.05;
v[1][1] = y;
v[1][2] = dtx->Zmax;
polyline( v, 2 );
if (dtx->CoordFlag) {
/* MJK 12.01.98 */
float2string(dtx, 1, row+1, str );
}
else {
/* MJK 12.01.98 */
float2string(dtx, 1, lat, str );
}
plot_string( str, x-0.07, y, dtx->Zmax, b3, u3, 1 );
}
else if (cc >= dtx->Nc-1) {
/* draw on top-east edge */
v[0][0] = x;
v[0][1] = y;
v[0][2] = dtx->Zmax;
v[1][0] = x+0.05;
v[1][1] = y;
v[1][2] = dtx->Zmax;
polyline( v, 2 );
if (dtx->CoordFlag) {
/* MJK 12.01.98 */
float2string(dtx, 1, row+1, str );
}
else {
/* MJK 12.01.98 */
float2string(dtx, 1, lat, str );
}
plot_string( str, x+0.07, y, dtx->Zmax, b2, u2, 0 );
}
else if (rr <=0) {
/* draw on top-north edge */
v[0][0] = x;
v[0][1] = y;
v[0][2] = dtx->Zmax;
v[1][0] = x;
v[1][1] = y+0.05;
v[1][2] = dtx->Zmax;
polyline( v, 2 );
if (dtx->CoordFlag) {
/* MJK 12.01.98 */
float2string(dtx, 0, col+1.0, str );
}
else {
/* MJK 12.01.98 */
float2string(dtx, 0, lon, str );
}
plot_string( str, x-0.07, y+0.07, dtx->Zmax, b2,u2, 0 );
}
else {
/* draw on top-south edge */
v[0][0] = x;
v[0][1] = y;
v[0][2] = dtx->Zmax;
v[1][0] = x;
v[1][1] = y-0.05;
v[1][2] = dtx->Zmax;
polyline( v, 2 );
if (dtx->CoordFlag) {
/* MJK 12.01.98 */
float2string(dtx, 0, col+1.0, str );
}
else {
/* MJK 12.01.98 */
float2string(dtx, 0, lon, str );
}
plot_string( str, x-0.07, y-0.12, dtx->Zmax, b2,u2, 0 );
}
}
/*
* Print the current cursor position.
*/
static void print_cursor_position( Display_Context dtx, int it )
{
static float bx[3] = { 0.05, 0.0, 0.0 }, ux[3] = { 0.0, 0.05, 0.05 };
static float by[3] = { -0.035, 0.0, -0.035 }, uy[3] = { 0.0, 0.07, 0.0 };
static float bz[3] = { -0.035, -0.035, 0.0 }, uz[3] = { 0.0, 0.0, 0.07 };
float v[6][3];
float x, y, z, xx, yy;
char str[100], xdir1[8],ydir1[8];
/* MJK 12.01.98 */
float lat, lon, hgt, row, col, lev;
int ix;
char fmt[] = {"%s: %9.3f %s "};
/* MiB 03/2001 Longitudes in [-180, 180] Intitialize...*/
xdir1[0] = ' ';
xdir1[1] = '\0';
ydir1[0] = ' ';
ydir1[1] = '\0';
/* MJK 12.01.98 begin*/
if ((dtx->DisplayProbe) || (dtx->DisplaySound)){
/* MJK 3.29.99 */
if (dtx->Reversed){
set_color (PACK_COLOR(0,0,0,255));
}
else{
set_color (dtx->BoxColor);
}
}
else{
set_color( *dtx->CursorColor );
}
/* end MJK 12.01.98 */
if (dtx->Projection==PROJ_LINEAR || dtx->Projection==PROJ_GENERIC) {
/* Rectangular box: put labels along edge of box in 3-D */
set_depthcue( dtx->DepthCue );
/* draw tick marks */
v[0][0] = v[1][0] = dtx->CursorX;
v[0][1] = dtx->Ymin; v[1][1] = dtx->Ymin-0.05;
v[0][2] = dtx->Zmin; v[1][2] = dtx->Zmin-0.05;
v[2][0] = dtx->Xmin; v[3][0] = dtx->Xmin-0.05;
v[2][1] = v[3][1] = dtx->CursorY;
v[2][2] = dtx->Zmin; v[3][2] = dtx->Zmin-0.05;
v[4][0] = dtx->Xmin; v[5][0] = dtx->Xmin-0.05;
v[4][1] = dtx->Ymin; v[5][1] = dtx->Ymin-0.05;
v[4][2] = v[5][2] = dtx->CursorZ;
if (dtx->DisplaySound) {
v[5][0] = 0;
v[5][1] = 0;
v[4][0] = 0;
v[4][1] = 0;
}
disjointpolyline( v, 6 );
/* draw position labels */
if (dtx->CoordFlag) {
/* display cursor position in grid coordinates */
xyzPRIME_to_gridPRIME( dtx, it, -1,
dtx->CursorX, dtx->CursorY, dtx->CursorZ, &y, &x, &z );
x += 1.0;
y += 1.0;
z += 1.0;
}
else {
/* display cursor position in geographic coordinates */
xyzPRIME_to_geo( dtx, it, -1,
dtx->CursorX, dtx->CursorY, dtx->CursorZ, &y, &x, &z );
z = VERTPRIME(z);
}
/*MiB 03/2001 limit range to -180, 180 */
xx = x;
if (xx < -180.){
xx = 360. + xx;
}
if (xx > 180.){
xx = -360. + xx;
}
/*MiB 03/2001 Define East/West */
if (xx > 0.){
xdir1[0] = 'W';
} else {
xdir1[0] = 'E';
xx = xx *(-1.);
}
/*MiB 03/2001 Define North/South */
yy = y;
if (yy > 0.){
ydir1[0] = 'N';
} else {
ydir1[0] = 'S';
yy = yy *(-1.);
}
/* MJK 12.01.98 */
float2string(dtx, 0, xx, str );
/*MiB*/ strcat(str,xdir1);
plot_string( str, dtx->CursorX-0.04, dtx->Ymin-0.1,
dtx->Zmin-0.125, bx, ux, 0 );
float2string(dtx, 1, yy, str );
/*MiB*/ strcat(str,ydir1);
plot_string( str, dtx->Xmin-0.075, dtx->CursorY-0.02,
dtx->Zmin-0.075, by, uy, 1 );
float2string(dtx, 2, z, str );
if (!dtx->DisplaySound)
plot_string( str, dtx->Xmin-0.07, dtx->Ymin-0.07,
dtx->CursorZ+0.005, bz, uz, 1 );
set_depthcue( 0 );
}
/* MJK 12.01.98 */
ix = dtx->Nr;
if (dtx->Nc > ix) ix = dtx->Nc;
if (dtx->MaxNl > ix) ix = dtx->MaxNl;
x = ix;
v[0][0] = dtx->Xmin, v[0][1] = dtx->Ymin, v[0][2] = dtx->Zmin;
v[1][0] = dtx->Xmax, v[1][1] = dtx->Ymax, v[1][2] = dtx->Zmax;
v[2][0] = dtx->Xmin, v[2][1] = dtx->Ymax, v[2][2] = dtx->Zmax;
v[3][0] = dtx->Xmax, v[3][1] = dtx->Ymin, v[3][2] = dtx->Zmax;
for (ix = 0; ix < 4; ix++)
{
xyzPRIME_to_geo (dtx, it, -1, v[ix][0], v[ix][1], v[ix][2],
&lat, &lon, &hgt);
if (lat < 0.0) lat = -lat;
if (lon < 0.0) lon = -lon;
hgt = VERTPRIME(hgt);
if (lat > x) x = lat;
if (lon > x) x = lon;
if (hgt > x) x = hgt;
}
sprintf (str, "%.3f", x);
ix = strchr (str, '.') - str;
if (ix < 1) ix = 1;
fmt[5] = (ix + 4) + '0';
sprintf (str, fmt, "XXX", x, "xx");
ix = dtx->WinWidth - (text_width (dtx->gfx[WINDOW_3D_FONT]->font,str));
if (dtx->CoordFlag) {
/* display cursor position in grid coordinates */
xyzPRIME_to_gridPRIME (dtx, it, -1,
dtx->CursorX, dtx->CursorY, dtx->CursorZ,
&row, &col, &lev);
sprintf( str, "Row: %g", row+1.0 );
draw_text( ix, (dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE), str );
sprintf( str, "Col: %g", col+1.0 );
draw_text( ix, 2*(dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE), str );
if (!dtx->DisplaySound)
{
sprintf( str, "Lev: %g", lev+1.0 );
draw_text( ix, 3*(dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE), str );
}
}
else {
/* display cursor position in geographic coordinates */
xyzPRIME_to_geo (dtx, it, -1, dtx->CursorX, dtx->CursorY, dtx->CursorZ,
&lat, &lon, &hgt);
if (dtx->Projection == PROJ_GENERIC)
{
sprintf (str, fmt, "Row", lat, "");
draw_text( ix, (dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE), str );
sprintf (str, fmt, "Col", lon, "");
draw_text( ix, 2*(dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE), str );
}
else
{
char hemi[] = {"X"};
/* hemispheres are "Wisconsin-centric" ;-) */
hemi[0] = 'N';
if (lat < 0.0) lat = -lat, hemi[0] = 'S';
sprintf (str, fmt, "Lat", lat, hemi);
draw_text( ix, (dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE), str );
hemi[0] = 'W';
if (lon < 0.0) lon = -lon, hemi[0] = 'E';
/*MiB*/ if (lon > 180.) lon = -360. + lon, hemi[0] = 'W';
/*MiB*/ if (lon < 0.0) lon = -lon, hemi[0] = 'E';
sprintf (str, fmt, "Lon", lon, hemi);
draw_text( ix, 2*(dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE), str );
}
if (!dtx->DisplaySound)
{
if (dtx->VerticalSystem == VERT_NONEQUAL_MB)
sprintf (str, fmt, "Hgt", VERTPRIME(hgt), "mb");
else
sprintf (str, fmt, "Hgt", hgt, "km");
draw_text( ix, 3*(dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE), str );
}
}
/* end MJK 12.01.98 */
}
/*
* Examine the entries of a color lookup table to determine the alpha value.
* If the alpha is the same for all entries return that value. If the
* alpha varies between entries return -1.
* Input: color_table - array of color values
* size - number of entries in table
* Return: -1 or constant alpha value
*/
int get_alpha( unsigned int color_table[], int size )
{
int alpha, i;
/* Check for variable vs. constant alpha */
alpha = UNPACK_ALPHA( color_table[0] );
for (i=0;i<size;i++) {
if (UNPACK_ALPHA(color_table[i])!=alpha) {
return -1;
}
}
return alpha;
}
/*
* Render all isosurfaces selected for display.
* Input: ctx - the context
* time - dtx time!!
* tf - transparency flag: 1=only draw opaque surfaces
* 0=only draw transparent surfaces
*/
static void render_isosurfaces( Context ctx, int dtxtime, int ctxtime, int tf, int animflag )
{
int var, alpha, lock;
Display_Context dtx;
int time, colorvar, cvowner;
dtx = ctx->dpy_ctx;
for (var=0;var<ctx->NumVars;var++) {
if (ctx->SameIsoColorVarOwner[var] ||
ctx->IsoColorVar[var] < 0){
time = ctxtime;
}
else{
time = dtxtime;
}
if(ctx->DisplaySurf[var] && !ctx->Variable[var]->SurfTable[time]){
ctx->Variable[var]->SurfTable[time] = (struct isosurface *) allocate(ctx,sizeof(struct isosurface));
memset(ctx->Variable[var]->SurfTable[time], 0, sizeof(struct isosurface));
}
if (ctx->DisplaySurf[var] && ctx->Variable[var]->SurfTable[time]->valid) {
if (animflag) {
lock = cond_read_lock( &ctx->Variable[var]->SurfTable[time]->lock );
}
else {
wait_read_lock( &ctx->Variable[var]->SurfTable[time]->lock );
lock = 1;
}
if (lock) {
recent( ctx, ISOSURF, var );
colorvar = ctx->Variable[var]->SurfTable[time]->colorvar;
cvowner = ctx->Variable[var]->SurfTable[time]->cvowner;
/* Determine alpha for surface: -1=variable, 0..255=constant */
if (ctx->Variable[var]->SurfTable[time]->colors) {
alpha = UNPACK_ALPHA( dtx->Color[ctx->context_index*MAXVARS+
var][ISOSURF] );
/* alpha = get_alpha( ctx->ColorTable[VIS5D_ISOSURF_CT]->Colors[colorvar], 255 ); WLH 16 Aug 97 */
}
else {
alpha = UNPACK_ALPHA( dtx->Color[ctx->context_index*MAXVARS+
var][ISOSURF] );
}
if ( (tf && alpha==255) || (tf==0 && alpha<255) ) {
if (ctx->Variable[var]->SurfTable[time]->colors) {
int fastdraw;
vis5d_check_fastdraw(dtx->dpy_context_index, &fastdraw);
if ((fastdraw || animflag) && ctx->Variable[var]->SurfTable[time]->deci_verts) {
if (ctx->Variable[var]->SurfTable[time]->deci_colors) {
draw_colored_isosurface(
ctx->Variable[var]->SurfTable[time]->deci_numverts,
ctx->Variable[var]->SurfTable[time]->index,
(void *) ctx->Variable[var]->SurfTable[time]->deci_verts,
(void *) ctx->Variable[var]->SurfTable[time]->deci_norms,
1,
(void *) ctx->Variable[var]->SurfTable[time]->deci_colors,
dtx->ColorTable[VIS5D_ISOSURF_CT]->Colors[cvowner*MAXVARS+colorvar],
alpha
);
}
else {
draw_isosurface(
ctx->Variable[var]->SurfTable[time]->deci_numverts,
ctx->Variable[var]->SurfTable[time]->index,
(void *) ctx->Variable[var]->SurfTable[time]->deci_verts,
(void *) ctx->Variable[var]->SurfTable[time]->deci_norms,
1,
dtx->Color[ctx->context_index*MAXVARS+var][0],
NULL, GL_COMPILE
);
}
}
else
draw_colored_isosurface(
ctx->Variable[var]->SurfTable[time]->numindex,
ctx->Variable[var]->SurfTable[time]->index,
(void *) ctx->Variable[var]->SurfTable[time]->verts,
(void *) ctx->Variable[var]->SurfTable[time]->norms,
0,
(void *) ctx->Variable[var]->SurfTable[time]->colors,
dtx->ColorTable[VIS5D_ISOSURF_CT]->Colors[cvowner*MAXVARS+colorvar],
alpha );
}
else
{
draw_isosurface( ctx->Variable[var]->SurfTable[time]->numindex,
ctx->Variable[var]->SurfTable[time]->index,
(void *) ctx->Variable[var]->SurfTable[time]->verts,
(void *) ctx->Variable[var]->SurfTable[time]->norms,
0,
dtx->Color[ctx->context_index*MAXVARS+var][0], NULL, 0 );
}
}
}
done_read_lock( &ctx->Variable[var]->SurfTable[time]->lock );
}
}
}
static void render_hclips( Display_Context dtx, int animflag)
{
int i;
for (i = 0; i < 2; i++){
if (dtx->HClipTable[i].highlight == 1){
set_color( PACK_COLOR(100,25,240,255));
set_line_width(4);
}
else{
set_color( PACK_COLOR(50,200,75,255));
set_line_width(1);
}
polyline( (void *) dtx->HClipTable[i].boxverts,
dtx->HClipTable[i].numboxverts);
/* MJK 3.29.99 */
if (dtx->Reversed){
set_color( PACK_COLOR(0,0,0,255) );
}
else{
set_color( dtx->BoxColor );
}
set_line_width(dtx->LineWidth);
}
}
static void render_vclips( Display_Context dtx, int animflag)
{
int i;
for (i = 0; i < 4; i++){
if (dtx->VClipTable[i].highlight == 1){
set_color( PACK_COLOR(100,25,240,255));
set_line_width(4);
}
else{
set_color( PACK_COLOR(50,200,75,255));
set_line_width(1);
}
polyline( (void *) dtx->VClipTable[i].boxverts,
dtx->VClipTable[i].numboxverts);
if (dtx->VClipTable[i].highlight == 1){
float vert[4][3];
float zbot, ztop, x1, x2, y1, y2;
float llev, hlev;
llev = (float) dtx->LowLev;
hlev = (float) (dtx->Nl-1+dtx->LowLev);
gridPRIME_to_xyzPRIME( dtx, 0, 0, 1, &dtx->VClipTable[i].r1,
&dtx->VClipTable[i].c1, &llev,
&x1, &y1, &zbot);
gridPRIME_to_xyzPRIME( dtx, 0, 0, 1, &dtx->VClipTable[i].r2,
&dtx->VClipTable[i].c2, &hlev,
&x2, &y2, &ztop);
vert[0][0] = vert[1][0] = vert[2][0] = vert[3][0] = (x1 + x2)*0.5;
vert[0][1] = vert[1][1] = vert[2][1] = vert[3][1] = (y1 +y2)*0.5;
vert[0][2] = ztop+TICK_SIZE;
vert[1][2] = ztop;
vert[2][2] = zbot;
vert[3][2] = zbot-TICK_SIZE;
set_line_width(5);
disjointpolyline( vert, 4 );
}
/* MJK 3.29.99 */
if (dtx->Reversed){
set_color( PACK_COLOR(0,0,0,255) );
}
else{
set_color( dtx->BoxColor );
}
set_line_width(dtx->LineWidth);
}
}
static void render_textplots( Irregular_Context itx, int time)
{
int var;
float a, b, c, d;
vis5d_get_text_plot(itx->context_index, &var, &a, &b, &c, &d);
if (itx->DisplayTextPlot && itx->TextPlotTable[time].valid){
if (itx->TextPlotTable[time].colors){
draw_colored_disjoint_lines(itx->TextPlotTable[time].numverts,
(void *) itx->TextPlotTable[time].verts,
(void *) itx->TextPlotTable[time].colors,
itx->dpy_ctx->ColorTable[VIS5D_TEXTPLOT_CT]->Colors[itx->context_index*
MAXVARS+var]);
}
else{
draw_disjoint_lines( itx->TextPlotTable[time].numverts,
(void *) itx->TextPlotTable[time].verts,
itx->dpy_ctx->TextPlotColor[itx->context_index*
MAXVARS+var] , NULL, 0);
}
}
}
/*
* Render all horizontal contour slices selected for display.
* Input: ctx - the context
* time - the time step
* labels - draw labels flag.
*/
static void render_hslices( Context ctx, int time, int labels, int animflag )
{
int var, lock;
if(vis5d_verbose & VERBOSE_RENDER) printf("render_hslices %d %d %d\n",time,labels,animflag);
for (var=0;var<ctx->NumVars;var++) {
if (ctx->DisplayHSlice[var] && ctx->Variable[var]->HSliceTable[time] &&
ctx->Variable[var]->HSliceTable[time]->valid) {
if (animflag) {
lock = cond_read_lock(&(ctx->Variable[var]->HSliceTable[time]->lock));
}
else {
wait_read_lock(&(ctx->Variable[var]->HSliceTable[time]->lock));
lock = 1;
}
if (lock) {
recent( ctx, HSLICE, var );
if(ctx->Variable[var]->HSliceRequest->stipple!=VIS5D_SOLID_LINE){
glEnable(GL_LINE_STIPPLE);
glLineStipple(1, (GLushort) ctx->Variable[var]->HSliceRequest->stipple);
}
if(ctx->Variable[var]->HSliceRequest->linewidth>1)
glLineWidth(ctx->Variable[var]->HSliceRequest->linewidth);
/* draw main contour lines */
draw_disjoint_lines( ctx->Variable[var]->HSliceTable[time]->num1,
(void *) ctx->Variable[var]->HSliceTable[time]->verts1,
ctx->dpy_ctx->Color[ctx->context_index*MAXVARS+var][HSLICE],
NULL, 0 );
if (labels) {
#ifdef USE_SYSTEM_FONTS
/* draw hidden contour lines */
draw_disjoint_lines( ctx->Variable[var]->HSliceTable[time]->num2,
(void *)ctx->Variable[var]->HSliceTable[time]->verts2,
ctx->dpy_ctx->Color[ctx->context_index*MAXVARS+
var][HSLICE], NULL, 0 );
glDisable(GL_LINE_STIPPLE);
plot_strings( ctx->Variable[var]->HSliceTable[time]->num3,
ctx->Variable[var]->HSliceTable[time]->labels,
ctx->Variable[var]->HSliceTable[time]->verts3,
ctx->dpy_ctx->Color[ctx->context_index*MAXVARS+var][HSLICE],
ctx->dpy_ctx->gfx[CONTOUR_LABEL_FONT]->fontbase );
#else
draw_disjoint_lines( ctx->Variable[var]->HSliceTable[time]->num3,
(void *)ctx->Variable[var]->HSliceTable[time]->verts3,
ctx->dpy_ctx->Color[ctx->context_index*MAXVARS
+var][HSLICE], NULL, 0 );
#endif
}
else {
/* draw hidden contour lines */
draw_disjoint_lines( ctx->Variable[var]->HSliceTable[time]->num2,
(void *)ctx->Variable[var]->HSliceTable[time]->verts2,
ctx->dpy_ctx->Color[ctx->context_index*MAXVARS+
var][HSLICE], NULL, 0 );
}
/* draw the bounding box */
glLineWidth(1);
glDisable(GL_LINE_STIPPLE);
/* MJK 12.01.98 */
if (!ctx->DisplaySfcHSlice[var]){
polyline( (void *) ctx->Variable[var]->HSliceTable[time]->boxverts,
ctx->Variable[var]->HSliceTable[time]->numboxverts );
}
done_read_lock( &ctx->Variable[var]->HSliceTable[time]->lock );
}
/* draw position label */
/* MJK 12.01.98 */
if (!ctx->DisplaySfcHSlice[var]){
if (ctx->dpy_ctx->DisplayBox && !ctx->dpy_ctx->CurvedBox) {
float l, z;
l = ctx->Variable[var]->HSliceRequest->Level;
z = height_to_zPRIME( ctx->dpy_ctx, ctx->Variable[var]->HSliceRequest->Hgt);
clipping_off();
draw_horizontal_slice_tick( ctx->dpy_ctx,l, z, ctx->Variable[var]->HSliceRequest->Hgt);
clipping_on();
}
}
}
}
}
/*
* Render all vertical contour slices selected for display.
* Input: ctx - the context
* time - the time step
* labels - draw labels flag.
*/
static void render_vslices( Context ctx, int time, int labels, int animflag )
{
int var, lock;
float x1, x2,y1,y2,z1,z2;
float r1p, r2p, c1p, c2p, lp;
for (var=0;var<ctx->NumVars;var++) {
if (ctx->DisplayVSlice[var] && ctx->Variable[var]->VSliceTable[time]->valid) {
#ifndef USE_SYSTEM_FONTS
if (labels)
{
if (check_view_side (ctx, VSLICE, var) < 0)
{
printf("flip the slice ?\n");
flip_vslice_end_for_end (ctx, time, var);
}
}
#endif
if (animflag) {
lock = cond_read_lock(&ctx->Variable[var]->VSliceTable[time]->lock);
}
else {
wait_read_lock(&ctx->Variable[var]->VSliceTable[time]->lock);
lock = 1;
}
if (lock) {
recent( ctx, VSLICE, var );
if(ctx->Variable[var]->VSliceRequest->stipple!=VIS5D_SOLID_LINE){
glEnable(GL_LINE_STIPPLE);
glLineStipple(1, (GLushort) ctx->Variable[var]->VSliceRequest->stipple);
}
if(ctx->Variable[var]->VSliceRequest->linewidth>1)
glLineWidth(ctx->Variable[var]->VSliceRequest->linewidth);
/* draw main contour lines */
draw_disjoint_lines( ctx->Variable[var]->VSliceTable[time]->num1,
(void*) ctx->Variable[var]->VSliceTable[time]->verts1,
ctx->dpy_ctx->Color[ctx->context_index*MAXVARS+
var][VSLICE], NULL, 0 );
if (labels) {
#ifdef USE_SYSTEM_FONTS
/* draw hidden contour lines */
draw_disjoint_lines( ctx->Variable[var]->VSliceTable[time]->num2,
(void*) ctx->Variable[var]->VSliceTable[time]->verts2,
ctx->dpy_ctx->Color[ctx->context_index*MAXVARS+
var][VSLICE] , NULL, 0);
glDisable(GL_LINE_STIPPLE);
plot_strings( ctx->Variable[var]->VSliceTable[time]->num3,
ctx->Variable[var]->VSliceTable[time]->labels,
(void*) ctx->Variable[var]->VSliceTable[time]->verts3,
ctx->dpy_ctx->Color[ctx->context_index*MAXVARS+var][VSLICE],
ctx->dpy_ctx->gfx[CONTOUR_LABEL_FONT]->fontbase );
#else
/* draw contour labels */
draw_disjoint_lines( ctx->Variable[var]->VSliceTable[time]->num3,
(void*) ctx->Variable[var]->VSliceTable[time]->verts3,
ctx->dpy_ctx->Color[ctx->context_index*MAXVARS+
var][VSLICE] , NULL, 0);
#endif
}
else {
/* draw hidden contour lines */
draw_disjoint_lines( ctx->Variable[var]->VSliceTable[time]->num2,
(void*) ctx->Variable[var]->VSliceTable[time]->verts2,
ctx->dpy_ctx->Color[ctx->context_index*MAXVARS+
var][VSLICE] , NULL, 0);
}
/* draw the bounding box */
polyline( (void *) ctx->Variable[var]->VSliceTable[time]->boxverts,
ctx->Variable[var]->VSliceTable[time]->numboxverts );
done_read_lock( &ctx->Variable[var]->VSliceTable[time]->lock );
}
if (ctx->dpy_ctx->DisplayBox && !ctx->dpy_ctx->CurvedBox) {
/* draw position labels */
float vert[4][3];
float zbot, ztop;
zbot = gridlevelPRIME_to_zPRIME(ctx->dpy_ctx, time, var, (float) ctx->dpy_ctx->LowLev);
ztop = gridlevelPRIME_to_zPRIME(ctx->dpy_ctx, time, var,
(float) (ctx->dpy_ctx->Nl-1+ctx->dpy_ctx->LowLev));
set_color( ctx->dpy_ctx->Color[ctx->context_index*MAXVARS+var][VSLICE] );
r1p = ctx->Variable[var]->VSliceRequest->R1;
c1p = ctx->Variable[var]->VSliceRequest->R2;
r2p = ctx->Variable[var]->VSliceRequest->C1;
c2p = ctx->Variable[var]->VSliceRequest->C2;
lp= 0.0;
gridPRIME_to_xyzPRIME( ctx->dpy_ctx, time, var, 1, &r1p, &c1p, &lp, &x1, &y1, &z1);
gridPRIME_to_xyzPRIME( ctx->dpy_ctx, time, var, 1, &r2p, &c2p, &lp, &x2, &y2, &z2);
clipping_off();
draw_vertical_slice_tick(ctx->dpy_ctx, r1p, c1p, x1, y1,
ctx->Variable[var]->VSliceRequest->Lat1, ctx->Variable[var]->VSliceRequest->Lon1 );
draw_vertical_slice_tick(ctx->dpy_ctx, r2p, c2p, x2, y2,
ctx->Variable[var]->VSliceRequest->Lat2,ctx->Variable[var]->VSliceRequest->Lon2 );
/*
draw_vertical_slice_tick( ctx->dpy_ctx, ctx->Variable[var]->VSliceRequest->R1,
ctx->Variable[var]->VSliceRequest->R2,
ctx->Variable[var]->VSliceRequest->X1,
ctx->Variable[var]->VSliceRequest->Y1,
ctx->Variable[var]->VSliceRequest->Lat1,
ctx->Variable[var]->VSliceRequest->Lon1 );
draw_vertical_slice_tick( ctx->dpy_ctx, ctx->Variable[var]->VSliceRequest->C1,
ctx->Variable[var]->VSliceRequest->C2,
ctx->Variable[var]->VSliceRequest->X2,
ctx->Variable[var]->VSliceRequest->Y2,
ctx->Variable[var]->VSliceRequest->Lat2,
ctx->Variable[var]->VSliceRequest->Lon2 );
*/
/* draw small markers at midpoint of top and bottom edges */
vert[0][0] = vert[1][0] = vert[2][0] = vert[3][0] = (x1 + x2)*0.5;
/*
(ctx->Variable[var]->VSliceRequest->X1 + ctx->Variable[var]->VSliceRequest->X2) * 0.5;
*/
vert[0][1] = vert[1][1] = vert[2][1] = vert[3][1] = (y1 +y2)*0.5;
/*
(ctx->Variable[var]->VSliceRequest->Y1 + ctx->Variable[var]->VSliceRequest->Y2) * 0.5;
*/
vert[0][2] = ztop+TICK_SIZE;
vert[1][2] = ztop;
vert[2][2] = zbot;
vert[3][2] = zbot-TICK_SIZE;
set_line_width(5); /* WLH 3-5-96 */
disjointpolyline( vert, 4 );
set_line_width(ctx->dpy_ctx->LineWidth); /* WLH 3-5-96 */
clipping_on();
}
}
}
}
/*
* Render all horizontal colored slices selected for display.
* Input: ctx - the context
* time - the timestep
* tf - transparency flag: 1=only draw opaque slices
* 0=only draw transparent slices
* animflag - 1=animating, 0=not animating
*/
static void render_chslices( Context ctx, int time, int tf, int animflag )
{
int var, alpha, lock;
Display_Context dtx;
dtx = ctx->dpy_ctx;
for (var=0;var<ctx->NumVars;var++) {
if (ctx->DisplayCHSlice[var]) {
if (ctx->Variable[var]->CHSliceTable[time]->valid) {
if (animflag) {
lock = cond_read_lock( &ctx->Variable[var]->CHSliceTable[time]->lock );
}
else {
wait_read_lock( &ctx->Variable[var]->CHSliceTable[time]->lock );
lock = 1;
}
if (lock) {
recent( ctx, CHSLICE, var );
if(!tf){
draw_color_quadmesh( ctx->Variable[var]->CHSliceTable[time]->rows,
ctx->Variable[var]->CHSliceTable[time]->columns,
(void *)ctx->Variable[var]->CHSliceTable[time]->verts,
ctx->Variable[var]->CHSliceTable[time]->color_indexes,
dtx->ColorTable[VIS5D_CHSLICE_CT]->Colors[ctx->context_index*MAXVARS+var],
0,NULL,0);
}
done_read_lock( &ctx->Variable[var]->CHSliceTable[time]->lock );
}
/* draw position label */
if (tf && dtx->DisplayBox && !dtx->CurvedBox) {
set_color( dtx->Color[ctx->context_index*MAXVARS+var][CHSLICE] );
clipping_off();
draw_horizontal_slice_tick( dtx, ctx->Variable[var]->CHSliceRequest->Level,
ctx->Variable[var]->CHSliceRequest->Z,
ctx->Variable[var]->CHSliceRequest->Hgt );
clipping_on();
}
}
}
}
}
/*
* Render all vertical colored slices selected for display.
* Input: ctx - the context
* time - the timestep
* tf - transparency flag: 1=only draw opaque slices
* 0=only draw transparent slices
*/
static void render_cvslices( Context ctx, int time, int tf, int animflag )
{
int var, alpha, lock;
float x1, x2,y1,y2,z1,z2;
float r1p, r2p, c1p, c2p, lp;
Display_Context dtx;
dtx = ctx->dpy_ctx;
for (var=0;var<ctx->NumVars;var++) {
if (ctx->DisplayCVSlice[var] && ctx->Variable[var]->CVSliceTable[time]->valid) {
if (animflag) {
lock = cond_read_lock(&ctx->Variable[var]->CVSliceTable[time]->lock);
}
else {
wait_read_lock(&ctx->Variable[var]->CVSliceTable[time]->lock);
lock = 1;
}
if (lock) {
recent( ctx, CVSLICE, var );
if ( !tf) {
draw_color_quadmesh( ctx->Variable[var]->CVSliceTable[time]->rows,
ctx->Variable[var]->CVSliceTable[time]->columns,
(void *)ctx->Variable[var]->CVSliceTable[time]->verts,
ctx->Variable[var]->CVSliceTable[time]->color_indexes,
dtx->ColorTable[VIS5D_CVSLICE_CT]->Colors[ctx->context_index*MAXVARS+var],
0,NULL,0 );
}
done_read_lock( &ctx->Variable[var]->CVSliceTable[time]->lock );
}
if (tf & dtx->DisplayBox && !dtx->CurvedBox) {
/* draw position labels */
float zbot, ztop;
float vert[4][3];
zbot = gridlevelPRIME_to_zPRIME(ctx->dpy_ctx, time, var, (float) ctx->dpy_ctx->LowLev);
ztop = gridlevelPRIME_to_zPRIME(ctx->dpy_ctx, time, var,
(float) (ctx->dpy_ctx->Nl-1+ctx->dpy_ctx->LowLev));
set_color( dtx->Color[ctx->context_index*MAXVARS+var][CVSLICE] );
r1p = ctx->Variable[var]->CVSliceRequest->R1;
c1p = ctx->Variable[var]->CVSliceRequest->R2;
r2p = ctx->Variable[var]->CVSliceRequest->C1;
c2p = ctx->Variable[var]->CVSliceRequest->C2;
lp= 0.0;
gridPRIME_to_xyzPRIME( ctx->dpy_ctx, time, var, 1, &r1p, &c1p, &lp, &x1, &y1, &z1);
gridPRIME_to_xyzPRIME( ctx->dpy_ctx, time, var, 1, &r2p, &c2p, &lp, &x2, &y2, &z2);
clipping_off();
draw_vertical_slice_tick(ctx->dpy_ctx, r1p, c1p, x1, y1,
ctx->Variable[var]->CVSliceRequest->Lat1, ctx->Variable[var]->CVSliceRequest->Lon1 );
draw_vertical_slice_tick(ctx->dpy_ctx, r2p, c2p, x2, y2,
ctx->Variable[var]->CVSliceRequest->Lat2,ctx->Variable[var]->CVSliceRequest->Lon2 );
/*
draw_vertical_slice_tick( dtx, ctx->Variable[var]->CVSliceRequest->R1,
ctx->Variable[var]->CVSliceRequest->R2,
ctx->Variable[var]->CVSliceRequest->X1,
ctx->Variable[var]->CVSliceRequest->Y1,
ctx->Variable[var]->CVSliceRequest->Lat1,
ctx->Variable[var]->CVSliceRequest->Lon1 );
draw_vertical_slice_tick( dtx, ctx->Variable[var]->CVSliceRequest->C1,
ctx->Variable[var]->CVSliceRequest->C2,
ctx->Variable[var]->CVSliceRequest->X2,
ctx->Variable[var]->CVSliceRequest->Y2,
ctx->Variable[var]->CVSliceRequest->Lat2,
ctx->Variable[var]->CVSliceRequest->Lon2 );
*/
/* draw small markers at midpoint of top and bottom edges */
vert[0][0] = vert[1][0] = vert[2][0] = vert[3][0] = (x1 + x2)*0.5;
vert[0][1] = vert[1][1] = vert[2][1] = vert[3][1] = (y1 +y2)*0.5;
/*
vert[0][0] = vert[1][0] = vert[2][0] = vert[3][0] =
(ctx->Variable[var]->CVSliceRequest->X1 + ctx->Variable[var]->CVSliceRequest->X2) * 0.5;
vert[0][1] = vert[1][1] = vert[2][1] = vert[3][1] =
(ctx->Variable[var]->CVSliceRequest->Y1 + ctx->Variable[var]->CVSliceRequest->Y2) * 0.5;
*/
vert[0][2] = ztop+TICK_SIZE;
vert[1][2] = ztop;
vert[2][2] = zbot;
vert[3][2] = zbot-TICK_SIZE;
set_line_width(5); /* WLH 3-5-96 */
disjointpolyline( vert, 4 );
set_line_width(dtx->LineWidth); /* WLH 3-5-96 */
clipping_on();
}
}
}
}
/*
* Render all horizontal wind vector slices which are selected for display.
* Input: ctx - the context
* time - the timestep
*/
static void render_hwind_slices( Context ctx, int time, int animflag )
{
int w, lock;
Display_Context dtx;
dtx = ctx->dpy_ctx;
for (w=0;w<VIS5D_WIND_SLICES;w++) {
if (dtx->DisplayHWind[w] && dtx->HWindTable[w][time].valid &&
ctx->context_index == dtx->Uvarowner[w]) {
if (animflag) {
lock = cond_read_lock( &dtx->HWindTable[w][time].lock );
}
else {
wait_read_lock( &dtx->HWindTable[w][time].lock );
lock = 1;
}
/* MJK 12.01.98 */
set_color( dtx->HWindColor[w] );
if (ctx->dpy_ctx->DisplaySfcHWind[w])
{
if (lock) {
recent( ctx, HWIND, w );
draw_disjoint_lines( dtx->HWindTable[w][time].nvectors,
(void *) dtx->HWindTable[w][time].verts,
dtx->HWindColor[w] , NULL, 0);
done_read_lock( &dtx->HWindTable[w][time].lock );
}
}
else
{
if (lock) {
recent( ctx, HWIND, w );
/* draw the bounding box */
polyline( (void *) dtx->HWindTable[w][time].boxverts,
dtx->HWindTable[w][time].numboxverts );
/* draw wind vectors */
if (dtx->HWindTable[w][time].barbs) {
draw_disjoint_lines( dtx->HWindTable[w][time].nvectors,
(void *) dtx->HWindTable[w][time].verts,
dtx->HWindColor[w], NULL, 0 );
}
else {
draw_wind_lines( dtx->HWindTable[w][time].nvectors / 4,
(void *) dtx->HWindTable[w][time].verts,
dtx->HWindColor[w] );
}
done_read_lock( &dtx->HWindTable[w][time].lock );
}
/* draw position label */
if (dtx->DisplayBox && !dtx->CurvedBox) {
clipping_off();
draw_horizontal_slice_tick( dtx, dtx->HWindLevel[w],
dtx->HWindZ[w], dtx->HWindHgt[w]);
clipping_on();
}
}
/* end MJK 12.01.98 */
}
}
}
/*
* Render all vertical wind vector slices which are selected for display.
* Input: ctx - the context
* time - the timestep
*/
static void render_vwind_slices( Context ctx, int time, int animflag )
{
int w, lock;
Display_Context dtx;
float x1, x2,y1,y2,z1,z2;
float r1p, r2p, c1p, c2p, lp;
dtx = ctx->dpy_ctx;
for (w=0;w<VIS5D_WIND_SLICES;w++) {
if (dtx->DisplayVWind[w] && dtx->VWindTable[w][time].valid &&
ctx->context_index == dtx->Uvarowner[w]) {
if (animflag) {
lock = cond_read_lock(&dtx->VWindTable[w][time].lock);
}
else {
wait_read_lock(&dtx->VWindTable[w][time].lock);
lock = 1;
}
if (lock) {
ctx = dtx->ctxpointerarray[0];
recent( ctx, VWIND, w );
/* draw the bounding box */
set_color( dtx->VWindColor[w] );
polyline( (void *) dtx->VWindTable[w][time].boxverts,
dtx->VWindTable[w][time].numboxverts );
/* draw wind vectors */
if (dtx->VWindTable[w][time].barbs) {
draw_disjoint_lines( dtx->VWindTable[w][time].nvectors,
(void *) dtx->VWindTable[w][time].verts,
dtx->VWindColor[w], NULL, 0 );
}
else {
draw_wind_lines( dtx->VWindTable[w][time].nvectors / 4,
(void *) dtx->VWindTable[w][time].verts,
dtx->VWindColor[w] );
}
done_read_lock( &dtx->VWindTable[w][time].lock );
}
if (dtx->DisplayBox && !dtx->CurvedBox) {
/* position labels */
float zbot, ztop;
float vert[4][3];
zbot = gridlevelPRIME_to_zPRIME(dtx, time, dtx->Uvar[w],
(float) dtx->LowLev);
ztop = gridlevelPRIME_to_zPRIME(dtx, time, dtx->Uvar[w],
(float) (dtx->Nl
+dtx->LowLev));
clipping_off();
r1p = dtx->VWindR1[w];
c1p = dtx->VWindC1[w];
r2p = dtx->VWindR2[w];
c2p = dtx->VWindC2[w];
lp= 0.0;
gridPRIME_to_xyzPRIME( dtx, time, dtx->Uvar[w], 1, &r1p, &c1p, &lp, &x1, &y1, &z1);
gridPRIME_to_xyzPRIME( dtx, time, dtx->Uvar[w], 1, &r2p, &c2p, &lp, &x2, &y2, &z2);
draw_vertical_slice_tick( dtx, r1p, c1p, x1, y1,
dtx->VWindLat1[w], dtx->VWindLon1[w] );
draw_vertical_slice_tick( dtx, r2p, c2p, x2, y2,
dtx->VWindLat2[w], dtx->VWindLon2[w] );
/* draw small markers at midpoint of top and bottom edges */
vert[0][0] = vert[1][0] = vert[2][0] = vert[3][0] =
(dtx->VWindX1[w] + dtx->VWindX2[w]) * 0.5;
vert[0][1] = vert[1][1] = vert[2][1] = vert[3][1] =
(dtx->VWindY1[w] + dtx->VWindY2[w]) * 0.5;
vert[0][2] = ztop+TICK_SIZE;
vert[1][2] = ztop;
vert[2][2] = zbot;
vert[3][2] = zbot-TICK_SIZE;
set_line_width(5); /* WLH 3-5-96 */
disjointpolyline( vert, 4 );
set_line_width(dtx->LineWidth); /* WLH 3-5-96 */
clipping_on();
}
}
}
}
/*
* Render all horizontal stream vector slices which are selected for display.
* Input: ctx - the context
* time - the timestep
*/
static void render_hstream_slices( Context ctx, int time, int animflag )
{
int w, lock;
Display_Context dtx;
dtx = ctx->dpy_ctx;
for (w=0;w<VIS5D_WIND_SLICES;w++) {
if (dtx->DisplayHStream[w] && dtx->HStreamTable[w][time].valid &&
ctx->context_index == dtx->Uvarowner[w]) {
if (animflag) {
lock = cond_read_lock(&dtx->HStreamTable[w][time].lock);
}
else {
wait_read_lock(&dtx->HStreamTable[w][time].lock);
lock = 1;
}
if (lock) {
ctx = dtx->ctxpointerarray[0];
recent( ctx, HSTREAM, w );
/* draw the bounding box */
set_color( dtx->HStreamColor[w] );
/* MJK 12.02.92 */
if (!ctx->dpy_ctx->DisplaySfcHStream[w]){
polyline( (void *) dtx->HStreamTable[w][time].boxverts,
dtx->HStreamTable[w][time].numboxverts );
}
/* draw main contour lines */
draw_disjoint_lines( dtx->HStreamTable[w][time].nlines,
(void *) dtx->HStreamTable[w][time].verts,
dtx->HStreamColor[w], NULL, 0 );
done_read_lock( &dtx->HStreamTable[w][time].lock );
}
/* draw position label */
/* MJK 12.02.92 */
if (!ctx->dpy_ctx->DisplaySfcHStream[w]){
if (dtx->DisplayBox && !dtx->CurvedBox) {
clipping_off();
draw_horizontal_slice_tick( dtx, dtx->HStreamLevel[w],
dtx->HStreamZ[w], dtx->HStreamHgt[w]);
clipping_on();
}
}
}
}
}
/*
* Render all vertical stream vector slices which are selected for display.
* Input: ctx - the context
* time - the timestep
*/
static void render_vstream_slices( Context ctx, int time, int animflag )
{
int w, lock;
Display_Context dtx;
dtx = ctx->dpy_ctx;
for (w=0;w<VIS5D_WIND_SLICES;w++) {
if (dtx->DisplayVStream[w] && dtx->VStreamTable[w][time].valid &&
ctx->context_index == dtx->Uvarowner[w]) {
if (animflag) {
lock = cond_read_lock(&dtx->VStreamTable[w][time].lock);
}
else {
wait_read_lock(&dtx->VStreamTable[w][time].lock);
lock = 1;
}
if (lock) {
ctx = dtx->ctxpointerarray[0];
recent( ctx, VSTREAM, w );
/* draw the bounding box */
set_color( dtx->VStreamColor[w] );
polyline( (void *) dtx->VStreamTable[w][time].boxverts,
dtx->VStreamTable[w][time].numboxverts );
/* draw main contour lines */
draw_disjoint_lines( dtx->VStreamTable[w][time].nlines,
(void *) dtx->VStreamTable[w][time].verts,
dtx->VStreamColor[w] , NULL, 0);
done_read_lock( &dtx->VStreamTable[w][time].lock );
}
if (dtx->DisplayBox && !dtx->CurvedBox) {
/* position labels */
float zbot, ztop;
float vert[4][3];
zbot = gridlevelPRIME_to_zPRIME(dtx, time, dtx->Uvar[w],
(float) dtx->LowLev);
ztop = gridlevelPRIME_to_zPRIME(dtx, time, dtx->Uvar[w],
(float) (dtx->Nl
+dtx->LowLev));
clipping_off();
draw_vertical_slice_tick( dtx, dtx->VStreamR1[w], dtx->VStreamC1[w],
dtx->VStreamX1[w], dtx->VStreamY1[w],
dtx->VStreamLat1[w], dtx->VStreamLon1[w] );
draw_vertical_slice_tick( dtx, dtx->VStreamR2[w], dtx->VStreamC2[w],
dtx->VStreamX2[w], dtx->VStreamY2[w],
dtx->VStreamLat2[w], dtx->VStreamLon2[w] );
/* draw small markers at midpoint of top and bottom edges */
vert[0][0] = vert[1][0] = vert[2][0] = vert[3][0] =
(dtx->VStreamX1[w] + dtx->VStreamX2[w]) * 0.5;
vert[0][1] = vert[1][1] = vert[2][1] = vert[3][1] =
(dtx->VStreamY1[w] + dtx->VStreamY2[w]) * 0.5;
vert[0][2] = ztop+TICK_SIZE;
vert[1][2] = ztop;
vert[2][2] = zbot;
vert[3][2] = zbot-TICK_SIZE;
set_line_width(5); /* WLH 3-5-96 */
disjointpolyline( vert, 4 );
set_line_width(dtx->LineWidth); /* WLH 3-5-96 */
clipping_on();
}
}
}
}
static void render_trajectories( Context ctx, int it, int tf )
{
int alpha, i, len, start;
Display_Context dtx;
dtx = ctx->dpy_ctx;
for (i=0;i<dtx->NumTraj;i++) {
struct traj *t = dtx->TrajTable[i];
if (t->ctx_owner==ctx->context_index
&& dtx->DisplayTraj[t->group]
&& cond_read_lock(&t->lock)){
assert( t->lock==1 );
recent( ctx, TRAJ, t->group );
alpha = UNPACK_ALPHA( dtx->TrajColor[t->group]);
if ( (tf && alpha==255) || (tf==0 && alpha<255) ) {
start = t->start[it];
len = t->len[it];
if (start!=0xffff && len>0) {
if (t->kind==0) {
/* draw as line segments */
int colorvar = t->colorvar;
if (colorvar>=0) {
/* draw colored trajectory */
draw_colored_polylines( len,
(void *) (t->verts + start*3),
(void*)(t->colors + start),
dtx->ColorTable[VIS5D_TRAJ_CT]->Colors[t->colorvarowner*MAXVARS+
colorvar]);
}
else {
/* monocolored */
draw_polylines( len,
(void *) (t->verts + start*3),
dtx->TrajColor[t->group] );
}
}
else {
/* draw as triangle strip */
int colorvar = t->colorvar;
if (colorvar>=0) {
/* draw colored triangles */
draw_colored_triangle_strip( len,
(void*)(t->verts + start*3),
(void*)(t->norms + start*3),
(void*)(t->colors + start),
dtx->ColorTable[VIS5D_TRAJ_CT]->Colors[t->colorvarowner*MAXVARS+
colorvar], alpha );
}
else {
/* monocolor */
draw_triangle_strip( len,
(void*)(t->verts + start*3),
(void*)(t->norms + start*3),
dtx->TrajColor[t->group] );
}
}
}
}
done_read_lock( &t->lock );
}
}
}
/*
* Draw the clock in the upper-left corner of the 3-D window.
* Input: ctx - the vis5d context
* c - the color to use.
*/
/* MJK 12.02.98 begin */
static void draw_clock( Display_Context dtx, unsigned int c )
{
static char day[7][20] = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday" };
static char month[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
static int dds[24] = {31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365,
31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
static float twopi = 2.0 * 3.141592;
short pp[CLOCK_SEGMENTS+1][2];
float ang, delta;
float clk_size, clk_margin, clk_radius, clk_center_x, clk_center_y;
char str[15];
int i, time_str_width;
int stime=0, stimeold, dtime=0, dtimeold;
clk_size = 4*(dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE);
clk_margin = clk_size / 16.0;
clk_radius = (clk_size / 2.0) - clk_margin;
clk_center_x = clk_size / 2.0;
clk_center_y = clk_size / 2.0;
/* Draw the clock. */
if (dtx->NumTimes)
ang = twopi * (float) dtx->CurTime / (float) dtx->NumTimes;
else
ang = 0.0;
pp[0][1] = clk_center_y;
pp[0][0] = clk_center_x;
pp[1][1] = clk_center_y - (clk_radius * cos(ang));
pp[1][0] = clk_center_x + (clk_radius * sin(ang));
pp[2][1] = pp[1][1] + 1;
pp[2][0] = pp[1][0] + 1;
pp[3][1] = pp[0][1] + 1;
pp[3][0] = pp[0][0] + 1;
pp[4][1] = pp[0][1] - 1;
pp[4][0] = pp[0][0] + 1;
pp[5][1] = pp[1][1] - 1;
pp[5][0] = pp[1][0] + 1;
set_color( c );
polyline2d( pp, 6 );
if (dtx->CircleClock){
/* Draw a circle around the clock. */
delta = twopi / ((float) CLOCK_SEGMENTS);
ang = 0.0;
for (i = 0; i < CLOCK_SEGMENTS; i++)
{
pp[i][0] = clk_center_x + (clk_radius * sin (ang)) + 0.5;
pp[i][1] = clk_center_y - (clk_radius * cos (ang)) + 0.5;
ang += delta;
}
pp[i][0] = pp[0][0];
pp[i][1] = pp[0][1];
polyline2d (pp, CLOCK_SEGMENTS+1);
}
clk_size += clk_margin;
dtimeold = -1;
stimeold = -1;
if(dtx->NumTimes)
vis5d_get_dtx_time_stamp( dtx->dpy_context_index,
dtx->CurTime,
&dtime, &stime);
dtimeold = dtime;
stimeold = stime;
i = stimeold;
sprintf( str, "%02d:%02d:%02d", i/3600, (i/60)%60, i%60 );
draw_text( clk_size, dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE, str );
time_str_width = text_width ( dtx->gfx[WINDOW_3D_FONT]->font, str);
if (dtx->JulianDate) {
sprintf( str, "%7d", v5dDaysToYYDDD( dtimeold ));
}
else {
int iyyddd, iy, im, id, mon;
iyyddd = v5dDaysToYYDDD( dtimeold );
iy = iyyddd / 1000;
id = iyyddd - (iy * 1000);
im = ((iy % 4) == 0 && ((iy % 100) != 0 || (iy % 400) == 0)) ? 12 : 0;
for (i=im; i<im+12; i++) {
if (id <= dds[i]) {
mon = i-im;
if (mon > 0) id = id - dds[i-1];
break;
}
}
sprintf(str, "%02d %s %02d", id, month[mon], iy);
}
draw_text( clk_size, 2*(dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE), str );
sprintf( str, "%d of %d", dtx->CurTime+1, dtx->NumTimes );
draw_text( clk_size, 3*(dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE), str );
if (dtx->NumTimes == 1 ||
((dtx->Elapsed[dtx->NumTimes-1] - dtx->Elapsed[0])
/ (dtx->NumTimes - 1)) < 48*3600 ) {
/* Print day of week */
draw_text( clk_size, 4*(dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE),
day[ (dtimeold+0) % 7 ] );
}
if (dtx->group_index > 0){
sprintf( str, " Group %d", dtx->group_index);
draw_text( (clk_size + time_str_width), (dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE), str );
}
}
/* MJK 12.02.98 end */
/*
* Render all the 2-D text labels.
*/
static void render_text_labels( Display_Context dtx )
{
struct label *lab;
for (lab=dtx->FirstLabel; lab; lab=lab->next) {
if (dtx->Reversed && lab->LabelColor==PACK_COLOR(255,255,255,255)){
set_color( PACK_COLOR(0,0,0,255) );
}
else{
set_color( lab->LabelColor );
}
draw_text( lab->x, lab->y, lab->text );
if (lab->state) {
/* being edited -> draw cursor */
short verts[4][2];
verts[0][0] = lab->x2; verts[0][1] = lab->y1;
verts[1][0] = lab->x2; verts[1][1] = lab->y2;
verts[2][0] = lab->x2+1; verts[2][1] = lab->y2;
verts[3][0] = lab->x2+1; verts[3][1] = lab->y1;
polyline2d( verts, 4 );
}
}
}
static void draw_fake_pointer( Display_Context dtx )
{
short pp[8][2];
pp[0][0] = dtx->PointerX; pp[0][1] = dtx->PointerY;
pp[1][0] = dtx->PointerX+15; pp[1][1] = dtx->PointerY+5;
pp[2][0] = dtx->PointerX+5; pp[2][1] = dtx->PointerY+15;
pp[3][0] = dtx->PointerX; pp[3][1] = dtx->PointerY;
pp[4][0] = dtx->PointerX+20; pp[4][1] = dtx->PointerY+20;
polyline2d( pp, 5 );
}
/*
* Print status info at bottom of window.
*/
static void print_info( Display_Context dtx )
{
char str[1000];
int m, size, waiters;
m = mem_used( dtx );
get_queue_info( &size, &waiters );
if (m>=0)
sprintf(str, "Pending: %d Memory Used: %d", size, m );
else
sprintf(str, "Pending: %d", size );
draw_text( 10, dtx->WinHeight - dtx->gfx[WINDOW_3D_FONT]->FontHeight, str );
}
/*
* Print the numeric value of each variable at the probe's current location.
*/
/* MJK 12.02.98 begin */
static void draw_probe( Display_Context dtx )
{
float val;
char str[1000];
int y, var;
int x;
int yo;
float rr,cc,ll;
/* find widest parameter name, but only once */
if (!dtx->do_not_recalc_probe_text_width){
x = -1;
for (yo = 0; yo < dtx->numofctxs; yo++){
for (var=0;var<dtx->ctxpointerarray[yo]->NumVars; var++) {
int w = text_width(dtx->gfx[WINDOW_3D_FONT]->font, dtx->ctxpointerarray[yo]->Variable[var]->VarName );
int l = strlen( dtx->ctxpointerarray[yo]->Variable[var]->VarName );
if (w < 1) w = 11 * l;
if (w>x)
x = w;
}
}
if (dtx->numofctxs >0){
x += 25;
}
dtx->do_not_recalc_probe_text_width = 1;
dtx->probe_text_width = x;
}
x = dtx->probe_text_width;
/* Draw from bottom of window upward */
y = dtx->WinHeight - dtx->gfx[WINDOW_3D_FONT]->FontHeight;
for (yo = 0; yo < dtx->numofctxs; yo++){
Context ctx;
int ipvar, npvar, lpvar;
ctx = dtx->ctxpointerarray[yo];
if (ctx->ProbeNumVars >= 0) {
npvar = ctx->ProbeNumVars;
lpvar = 1;
}
else {
npvar = ctx->NumVars - 1;
lpvar = 0;
}
for (ipvar = npvar; ipvar >= lpvar; ipvar--) {
var = ipvar;
if (ctx->ProbeNumVars > 0) {
for (var=ctx->NumVars-1;var>=0;var--) {
if (ctx->ProbeVar[var] == ipvar) break;
}
}
if (var >= 0) {
float r, c, l;
xyzPRIME_to_grid( ctx, ctx->CurTime, var,
dtx->CursorX, dtx->CursorY, dtx->CursorZ, &rr, &cc, &ll );
xyzPRIME_to_gridPRIME( ctx->dpy_ctx, dtx->CurTime, var, dtx->CursorX,
dtx->CursorY, dtx->CursorZ, &r, &c, &l);
if (ll < ctx->Variable[var]->LowLev || ll > ctx->Nl[var]-1 + ctx->Variable[var]->LowLev ||
rr < 0 || rr > ctx->Nr-1 || cc < 0 || cc > ctx->Nc-1 ||
!check_for_valid_time(ctx, dtx->CurTime)) {
val = MISSING;
}
else if (dtx->CoordFlag==1) {
/* discrete grid position */
int row = (int) (r+0.01);
int col = (int) (c+0.01);
int lev = (int) (l+0.01);
if (ctx->GridSameAsGridPRIME){
val = get_grid_value( ctx, ctx->CurTime, var, row, col, lev );
}
else{
vis5d_gridPRIME_to_grid(ctx->context_index, ctx->CurTime, var,
(float)(row), (float)(col), (float)(lev),
&rr, &cc, &ll);
if (ll < ctx->Variable[var]->LowLev || ll > ctx->Nl[var]-1 + ctx->Variable[var]->LowLev ||
rr < 0 || rr > ctx->Nr-1 || cc < 0 || cc > ctx->Nc-1) {
val = MISSING;
}
else{
val = get_grid_value( ctx, ctx->CurTime, var, rr, cc, ll);
}
}
}
else {
if (ctx->GridSameAsGridPRIME){
val = interpolate_grid_value( ctx, ctx->CurTime, var, r, c, l );
}
else{
val = interpolate_grid_value( ctx, ctx->CurTime, var, rr, cc, ll );
}
}
sprintf( str, "%-4s", ctx->Variable[var]->VarName );
if (dtx->numofctxs > 1){
char yodle[40];
strcpy(yodle, return_var_plus_index(str, ctx->context_index));
draw_text( 10, y, yodle );
}
else{
draw_text( 10, y, str);
}
if (IS_MISSING(val))
sprintf( str, " = MISSING" );
else
sprintf( str, " = %.3g %s", val, ctx->Variable[var]->Units );
draw_text( x+10, y, str );
y -= (dtx->gfx[WINDOW_3D_FONT]->FontHeight+VSPACE);
}
}
}
}
/* MJK 12.02.98 end */
/*
#define LEGEND_SPACE 20
#define LEGEND_WIDTH 25
#define LEGEND_HEIGHT 128
*/
#define TICK_LENGTH 4
#define NUM_TICKS 5
/*
* Draw a color legend.
* Input: var = parameter index the color slice belongs to for which to
* draw the legend,
* type = CHSLICE or CVSLICE,
* xleft = x-position for left side of color bar,
* ybot = y-position for bottom of color bar.
* Return: width of bar + numbers drawn, or height of bar + label.
*/
int draw_legend( Context ctx, int varowner, int var, int type, int xleft, int ybot )
{
int y,
lutindex,
textwidth;
int tick;
short cline[2][2];
uint *lut;
char scrap[100], format[20];
int legend_space, legend_width, legend_height;
float label;
Display_Context dtx;
Context colorctx;
/* MJK 12.02.98 */
int bg_r, bg_g, bg_b, bg_a, fg_r, fg_g, fg_b, fg_a;
dtx = ctx->dpy_ctx;
colorctx = dtx->ctxpointerarray[return_ctx_index_pos(dtx, varowner)];
legend_height = dtx->LegendSize;
legend_width = (25 * dtx->LegendSize) / 128;
legend_space = (20 * dtx->LegendSize) / 128;
switch(type) {
case VIS5D_ISOSURF:
lut = dtx->ColorTable[VIS5D_ISOSURF_CT]->Colors[varowner*MAXVARS+var];
break;
case VIS5D_CHSLICE:
lut = dtx->ColorTable[VIS5D_CHSLICE_CT]->Colors[varowner*MAXVARS+var];
break;
case VIS5D_CVSLICE:
lut = dtx->ColorTable[VIS5D_CVSLICE_CT]->Colors[varowner*MAXVARS+var];
break;
case VIS5D_TRAJ:
lut = dtx->ColorTable[VIS5D_TRAJ_CT]->Colors[varowner*MAXVARS+var];
break;
case VIS5D_VOLUME:
lut = dtx->ColorTable[VIS5D_VOLUME_CT]->Colors[varowner*MAXVARS+var];
break;
case VIS5D_TOPO:
lut = dtx->ColorTable[VIS5D_TOPO_CT]->Colors[varowner*MAXVARS+var];
break;
default:
/* this should never happen */
abort();
}
/* These line values never change */
cline[0][0] = xleft;
cline[1][0] = xleft + legend_width;
/* Draw the colors */
/* MJK 12.02.98 begin */
bg_r = UNPACK_RED(dtx->BgColor);
bg_g = UNPACK_GREEN(dtx->BgColor);
bg_b = UNPACK_BLUE(dtx->BgColor);
for (y = 0; y<legend_height; y++) {
lutindex = (255 * y)/legend_height;
cline[0][1] = cline[1][1] = ybot - y;
fg_r = UNPACK_RED(lut[lutindex]);
fg_g = UNPACK_GREEN(lut[lutindex]);
fg_b = UNPACK_BLUE(lut[lutindex]);
fg_a = UNPACK_ALPHA(lut[lutindex]);
bg_a = 255 - fg_a;
fg_r = ((fg_r * fg_a) + (bg_r * bg_a)) / 255;
fg_g = ((fg_g * fg_a) + (bg_g * bg_a)) / 255;
fg_b = ((fg_b * fg_a) + (bg_b * bg_a)) / 255;
set_color (PACK_COLOR(fg_r, fg_g, fg_b, 255));
polyline2d(cline, 2);
}
/* Draw a box around the legend colorbar */
/* MJK 3.29.99 */
if (dtx->Reversed) {
set_color(PACK_COLOR( 0, 0, 0, 255));
}
else{
set_color( dtx->BoxColor );
}
cline[0][0] = cline[1][0] = xleft;
cline[0][1] = ybot;
cline[1][1] = ybot - legend_height + 1;
polyline2d(cline, 2);
cline[0][0] = cline[1][0] = xleft + legend_width;
polyline2d(cline, 2);
cline[0][0] = xleft;
cline[1][0] = xleft + legend_width;
cline[0][1] = cline[1][1] = ybot;
polyline2d(cline, 2);
cline[0][1] = cline[1][1] = ybot - legend_height + 1;
polyline2d(cline, 2);
/* MJK 12.02.98 end */
/* Determine largest value physical variable can have */
label = ABS(colorctx->Variable[var]->MaxVal);
if (ABS(colorctx->Variable[var]->MinVal) > label)
label = ABS(colorctx->Variable[var]->MinVal);
/* Create 'pretty' formatting string */
sprintf(scrap, "% .0f", label);
sprintf(format, "%% %d.2f", (int)strlen(scrap)+3);
/* Draw values and tick marks on the right hand side of the legend */
textwidth = 0;
/* Make sure we have a tick at the top of the legend @@ */
cline[0][0] += TICK_LENGTH + legend_width;
/* MJK 3.29.99 */
if (dtx->Reversed) {
set_color(PACK_COLOR( 0, 0, 0, 255));
}
else{
set_color( dtx->BoxColor );
}
XSync( GfxDpy, 0 );
for (tick=0;tick<NUM_TICKS;tick++) {
int ticky, texty;
float value;
ticky = ybot - tick * (legend_height-1) / (NUM_TICKS-1);
texty = ybot - tick * (legend_height-dtx->gfx[WINDOW_3D_FONT]->FontHeight+dtx->gfx[WINDOW_3D_FONT]->FontDescent)
/ (NUM_TICKS-1);
value = colorctx->Variable[var]->MinVal + (colorctx->Variable[var]->MaxVal-colorctx->Variable[var]->MinVal)*tick/4.0;
cline[0][1] = cline[1][1] = ticky;
polyline2d(cline, 2);
sprintf(scrap, format, value);
draw_text( xleft + legend_width + TICK_LENGTH + 2, texty, scrap );
XSync( GfxDpy, 0 );
if (text_width(dtx->gfx[WINDOW_3D_FONT]->font,scrap) > textwidth)
textwidth = text_width(dtx->gfx[WINDOW_3D_FONT]->font,scrap);
}
/* Print name of physical variable above legend */
if (colorctx->Variable[var]->Units[0]) {
sprintf( scrap, "%s (%s)", colorctx->Variable[var]->VarName, colorctx->Variable[var]->Units );
draw_text( xleft, ybot - legend_height - dtx->gfx[WINDOW_3D_FONT]->FontDescent-2, scrap );
}
else {
draw_text( xleft, ybot - legend_height - dtx->gfx[WINDOW_3D_FONT]->FontDescent-2,
colorctx->Variable[var]->VarName);
}
if (dtx->LegendPosition == VIS5D_BOTTOM ||
dtx->LegendPosition == VIS5D_TOP) {
return legend_width + TICK_LENGTH + 5 + textwidth + legend_space;
}
else {
return legend_height + 5 + dtx->gfx[WINDOW_3D_FONT]->FontHeight + legend_space;
}
}
/*
* Draws color legends of activated color slices.
* Since the space in the 3-D window is restricted only one row of legends
* is drawn in the bottom of the 3-D window. The order of drawing is:
* first the legends of the horizontal slices for parameter 0..NumVars-1
* and then the vertical slices for parameter 0..NumVars-1.
*/
static void draw_color_legends( Display_Context dtx )
{
int var, set;
int left; /* Left x position of current legend */
int bottom; /* Bottom y position of current legend */
int inc, vert;
int vindex;
int ctxnum, cvar, cvowner;
Context ctx;
if (dtx->LegendPosition == VIS5D_BOTTOM) {
left = 50+dtx->LegendMarginX;
bottom = dtx->WinHeight - 20 + dtx->LegendMarginY;
vert = 0;
}
else if (dtx->LegendPosition == VIS5D_TOP) {
left = 200+dtx->LegendMarginX;
bottom = dtx->LegendSize + 5 + dtx->gfx[WINDOW_3D_FONT]->FontHeight + 25 + dtx->LegendMarginY;
vert = 0;
}
else if (dtx->LegendPosition == VIS5D_RIGHT) {
left = dtx->WinWidth - ((35 * dtx->LegendSize) / 128) - 5 * dtx->gfx[WINDOW_3D_FONT]->FontHeight+dtx->LegendMarginX;
bottom = dtx->LegendSize + 5 + dtx->gfx[WINDOW_3D_FONT]->FontHeight + 50 + dtx->LegendMarginY;
vert = 1;
}
else if (dtx->LegendPosition == VIS5D_LEFT) {
left = 20+dtx->LegendMarginX;
bottom = dtx->LegendSize + 5 + dtx->gfx[WINDOW_3D_FONT]->FontHeight + 100 + dtx->LegendMarginY;
vert = 1;
}
else {
printf("draw_color_legends: bad LegendPosition\n");
return;
}
/* Isosurface color tables */
for (ctxnum=0; ctxnum<dtx->numofctxs; ctxnum++){
ctx = dtx->ctxpointerarray[ctxnum];
for (var=0; var<ctx->NumVars; var++) {
cvar = ctx->IsoColorVar[var];
cvowner = ctx->IsoColorVarOwner[var];
if (ctx->DisplaySurf[var] && cvar>=0 ){
/* Draw legend at position (xstart, ystart) = upper left corner */
inc = draw_legend( ctx, cvowner, cvar, VIS5D_ISOSURF, left, bottom );
if (vert) {
bottom += inc;
if (bottom > dtx->WinHeight - 50) return;
}
else {
left += inc;
if (left > dtx->WinWidth - 150) return;
}
}
}
}
/* Find activated horizontal color slices */
for (ctxnum=0; ctxnum<dtx->numofctxs; ctxnum++){
ctx = dtx->ctxpointerarray[ctxnum];
for (var=0; var<ctx->NumVars; var++) {
if (ctx->DisplayCHSlice[var]) {
/* Draw legend at position (xstart, ystart) = upper left corner */
vindex = ctx->context_index;
inc = draw_legend( ctx, vindex, var, VIS5D_CHSLICE, left, bottom );
if (vert) {
bottom += inc;
if (bottom > dtx->WinHeight - 50) return;
}
else {
left += inc;
if (left > dtx->WinWidth - 150) return;
}
}
}
}
/* Find activated vertical color slices */
for (ctxnum=0; ctxnum<dtx->numofctxs; ctxnum++){
ctx = dtx->ctxpointerarray[ctxnum];
for (var=0; var<ctx->NumVars; var++) {
if (ctx->DisplayCVSlice[var]) {
/* Draw legend at position (xstart, ystart) = upper left corner */
vindex = ctx->context_index;
inc = draw_legend( ctx, vindex, var, VIS5D_CVSLICE, left, bottom );
if (vert) {
bottom += inc;
if (bottom > dtx->WinHeight - 50) return;
}
else {
left += inc;
if (left > dtx->WinWidth - 150) return;
}
}
}
}
/* Volume */
if (dtx->CurrentVolume>=0 ) {
/* Draw legend at position (xstart, ystart) = upper left corner */
inc = draw_legend( ctx, dtx->CurrentVolumeOwner,
dtx->CurrentVolume, VIS5D_VOLUME, left, bottom );
if (vert) {
bottom += inc;
if (bottom > dtx->WinHeight - 50) return;
}
else {
left += inc;
if (left > dtx->WinWidth - 150) return;
}
}
/* Trajectory color tables */
for (set=0; set<VIS5D_TRAJ_SETS; set++) {
int cvar = dtx->TrajColorVar[set];
int cvowner = dtx->TrajColorVarOwner[set];
if (dtx->DisplayTraj[set] && cvar>=0 ){
/* Draw legend at position (xstart, ystart) = upper left corner */
inc = draw_legend( ctx, cvowner, cvar, VIS5D_TRAJ, left, bottom );
if (vert) {
bottom += inc;
if (bottom > dtx->WinHeight - 50) return;
}
else {
left += inc;
if (left > dtx->WinWidth - 150) return;
}
}
}
/* Topo color table */
if (dtx->topo->TopoColorVar>=0 && dtx->topo->DisplayTopo) {
int cvar = dtx->topo->TopoColorVar;
int cvowner = dtx->topo->TopoColorVarOwner;
/* Draw legend at position (xstart, ystart) = upper left corner */
inc = draw_legend( ctx, cvowner, cvar, VIS5D_TOPO, left, bottom );
if (vert) {
bottom += inc;
if (bottom > dtx->WinHeight - 50) return;
}
else {
left += inc;
if (left > dtx->WinWidth - 150) return;
}
}
}
/*
* Draw anything the user wants in 3D.
* Drawing bounds are (Xmin,Ymin,Zmin) - (Xmax,Ymax,Zmax)
*/
static void draw_user_3d_graphics( Display_Context dtx )
{
}
/*
* Draw anything the user wants in 2D.
* Drawing bounds are (0,0) - (Width-1, Height-1), origin in upper-left corner.
*/
static void draw_user_2d_graphics( Display_Context dtx )
{
}
/*
* Only draw the 3-D elements of the scene. No matrix, viewport, etc
* operations are done here. This function is useful for the CAVE
* since it controls the viewing parameters.
* Input: ctx - the context
* animflag - 1=animating, 0=not animating
*/
void render_3d_only( Display_Context dtx, int animflag )
{
int yo, labels, i;
Context ctx;
Irregular_Context itx;
if (animflag){
labels = !dtx->ContnumFlag;
}
else{
labels = dtx->ContnumFlag;
}
/* Loop over antialiasing passes */
for (i=0; i < (dtx->PrettyFlag ? AA_PASSES : 1); i++) {
start_aa_pass(i);
/*** Draw 3-D lines ***/
clipping_off();
/* MJK 12.02.98 begin */
if (dtx->DisplayCursor)
{
if (dtx->DisplayProbe)
{
/* MJK 3.29.99 */
if (dtx->Reversed){
draw_cursor (dtx, 0, dtx->CursorX, dtx->CursorY, dtx->CursorZ,
PACK_COLOR(0,0,0,255));
}
else{
draw_cursor (dtx, 0, dtx->CursorX, dtx->CursorY, dtx->CursorZ,
dtx->BoxColor);
}
}
else if (dtx->DisplaySound)
{
/* MJK 3.29.99 */
if (dtx->Reversed){
draw_cursor (dtx, 2, dtx->CursorX, dtx->CursorY, 0,
PACK_COLOR(0,0,0,255));
}
else{
draw_cursor (dtx, 2, dtx->CursorX, dtx->CursorY, 0,
dtx->BoxColor);
}
}
else
{
draw_cursor (dtx, dtx->RibbonFlag,
dtx->CursorX, dtx->CursorY, dtx->CursorZ,
*dtx->CursorColor);
}
if (dtx->DisplayBox)
{
print_cursor_position (dtx, dtx->CurTime);
}
}
/* MJK 12.02.98 end */
clipping_on();
for (yo = 0; yo < dtx->numofitxs; yo++){
itx = dtx->itxpointerarray[yo];
render_textplots( itx, itx->CurTime);
}
for (yo= 0; yo < dtx->numofctxs; yo++){
ctx = dtx->ctxpointerarray[yo];
if (check_for_valid_time(ctx, dtx->CurTime)){
render_hslices( ctx, ctx->CurTime, labels, animflag );
render_vslices( ctx, ctx->CurTime, labels, animflag );
render_hwind_slices( ctx, ctx->CurTime, animflag );
render_vwind_slices( ctx, ctx->CurTime, animflag );
render_hstream_slices( ctx, ctx->CurTime, animflag );
render_vstream_slices( ctx, ctx->CurTime, animflag );
}
}
/* draw user graphics */
draw_user_3d_graphics( dtx );
/*** Draw opaque 3-D graphics ***/
/* MJK 12.02.98 begin */
set_depthcue( dtx->DepthCue );
if (dtx->topo && dtx->topo->TopoFlag && dtx->topo->DisplayTopo) {
set_depthcue(0);
draw_topo( dtx, dtx->CurTime, dtx->DisplayTexture, 0 );
}
else if (dtx->DisplayTexture) {
/* just draw flat textured image */
set_depthcue(0);
draw_topo( dtx, dtx->CurTime, 1, 1 );
}
if (dtx->MapFlag && dtx->DisplayMap) {
if (dtx->DisplaySfcMap) {
set_color( dtx->DarkMapColor );
draw_map( dtx, dtx->CurTime, 0 );
}
else {
set_color( dtx->LightMapColor );
draw_map( dtx, dtx->CurTime, 1 );
}
/* MJK 3.29.99 */
if (dtx->Reversed){
set_color( PACK_COLOR(0,0,0,255) );
}
else{
set_color( dtx->BoxColor );
}
}
set_depthcue(0);
/* MJK 12.02.98 end */
for (yo= 0; yo < dtx->numofctxs; yo++){
ctx = dtx->ctxpointerarray[yo];
if (check_for_valid_time(ctx, dtx->CurTime)){
if(ctx->DataGridList){
glCallList(ctx->DataGridList);
}
render_trajectories( ctx, ctx->CurTime, 1);
render_isosurfaces( ctx, dtx->CurTime, ctx->CurTime, 1, animflag );
render_chslices( ctx, ctx->CurTime, 1, animflag );
render_cvslices( ctx, ctx->CurTime, 1, animflag );
}
}
/*** Draw transparent 3-D objects ***/
for (yo= 0; yo < dtx->numofctxs; yo++){
ctx = dtx->ctxpointerarray[yo];
if (check_for_valid_time(ctx, dtx->CurTime)){
render_trajectories( ctx, ctx->CurTime, 0);
render_isosurfaces( ctx, dtx->CurTime, ctx->CurTime, 0, animflag );
render_chslices( ctx, ctx->CurTime, 0, animflag );
render_cvslices( ctx, ctx->CurTime, 0, animflag );
}
}
if (dtx->VolumeFlag==1 && dtx->CurrentVolume!=-1){
ctx = dtx->ctxpointerarray[return_ctx_index_pos(dtx,
dtx->CurrentVolumeOwner)];
if (check_for_valid_time(ctx, dtx->CurTime)){
draw_volume( ctx, ctx->CurTime, dtx->CurrentVolume,
dtx->ColorTable[VIS5D_VOLUME_CT]->Colors[ctx->context_index*MAXVARS+
dtx->CurrentVolume] );
}
}
end_aa_pass(i);
} /* aa passes */
}
/*
* Only draw the 2-D elements of the scene. No matrix, viewport, etc
* operations are done here.
* Input: ctx - the context
*/
void render_2d_only( Display_Context dtx )
{
if (dtx->DisplayClock) {
/* MJK 3.29.99 */
if (dtx->Reversed){
draw_clock( dtx, PACK_COLOR(0,0,0,255) );
draw_logo( dtx, PACK_COLOR(0,0,0,255) );
}
else{
draw_clock( dtx, dtx->BoxColor );
draw_logo( dtx, dtx->BoxColor );
}
}
if (dtx->DisplayInfo) {
print_info(dtx);
}
if (dtx->DisplayProbe) {
draw_probe(dtx);
}
if (dtx->DisplayCursor && dtx->DisplayBox) {
print_cursor_position( dtx, dtx->CurTime );
}
if (dtx->PointerX>=0 && dtx->PointerY>=0){
draw_fake_pointer(dtx); /* for remote widget mode */
}
/* MJK 3.29.99 */
/* Moved to render_text_labels JPE
if (dtx->Reversed){
set_color( PACK_COLOR(0,0,0,255) );
}
else{
set_color( dtx->LabelColor );
}
*/
render_text_labels(dtx);
/* Draw color map legends of color slices (as much as fit in window) */
if (dtx->DisplayLegends ) {
draw_color_legends(dtx);
}
draw_user_2d_graphics( dtx );
}
/*
*
* draw everything that belongs inside of
* the Sounding Graphics Window
*
*
*/
void render_sounding_only( Display_Context dtx, int pixmapflag )
{
if (dtx->DisplaySound) {
if ( pixmapflag == 1 ){
do_pixmap_art( dtx );
/* MJK 12.02.98 */
/*
draw_sounding(dtx, dtx->CurTime);
*/
}
if ((dtx->CursorX != dtx->Sound.currentX ||
dtx->CursorY != dtx->Sound.currentY) ||
(dtx->CurTime != dtx->Sound.currentTime) ||
/* MJK 12.02.98 */ (pixmapflag)){
if (dtx->CurTime != dtx->Sound.currentTime){
reload_sounding_data( dtx );
}
draw_sounding(dtx, dtx->CurTime);
dtx->Sound.currentX = dtx->CursorX;
dtx->Sound.currentY = dtx->CursorY;
dtx->Sound.currentTime = dtx->CurTime;
}
}
}
/*
* Redraw everything in the 3-D window but don't display it yet. Call
* swap_3d_window() to do that.
* Input: ctx - the vis5d context
* animflag - 1=animating, 0=notanimating
* Return: 0 = ok, -1 = error.
*/
void render_everything( Display_Context dtx, int animflag )
{
if (get_frame(dtx, dtx->CurTime)) {
return;
}
/*** Draw 3-D Objects ***/
set_3d( dtx->GfxProjection, dtx->FrntClip,
dtx->Zoom, (float*) dtx->CTM);
if(dtx->StereoOn){
/*
* The set_3d call should have set the model matrix and the
* projection matrix correctly. The stereo_set_3d_perspective
* call just changes the projection matrix slightly.
*/
/* left eye */
stereo_set_3d_perspective(VIS5D_STEREO_LEFT,dtx->FrntClip);
stereo_set_buff(VIS5D_STEREO_LEFT);
clear_color (dtx->BgColor);
clear_3d_window();
if (dtx->DisplayBox){
int i;
for (i=0; i < (dtx->PrettyFlag ? AA_PASSES : 1); i++) {
start_aa_pass(i);
draw_box(dtx, dtx->CurTime);
/* draw_tick_marks( dtx ); */
end_aa_pass(i);
}
}
clipping_on();
render_3d_only( dtx, animflag );
clipping_off();
if (dtx->DisplayClips){
render_vclips( dtx, animflag );
render_hclips( dtx, animflag );
}
/* right eye */
stereo_set_3d_perspective(VIS5D_STEREO_RIGHT,dtx->FrntClip);
stereo_set_buff(VIS5D_STEREO_RIGHT);
clear_color (dtx->BgColor);
clear_3d_window();
if (dtx->DisplayBox){
int i;
for (i=0; i < (dtx->PrettyFlag ? AA_PASSES : 1); i++) {
start_aa_pass(i);
draw_box(dtx, dtx->CurTime);
/* draw_tick_marks( dtx ); */
end_aa_pass(i);
}
}
clipping_on();
render_3d_only( dtx, animflag );
clipping_off();
if (dtx->DisplayClips){
render_vclips( dtx, animflag );
render_hclips( dtx, animflag );
}
/* reset to default draw buffer */
stereo_set_buff(VIS5D_STEREO_BOTH);
}else{
/*
* The clear_3d_window call was moved out of vis5d_draw_frame and moved
* down into this function so stereo and mono rendering loops can both
* work with the same higher level api function.
*/
clear_3d_window();
clear_color (dtx->BgColor);
if (dtx->DisplayBox){
int i, listflag=0;
for (i=0; i < (dtx->PrettyFlag ? AA_PASSES : 1); i++) {
start_aa_pass(i);
draw_box(dtx, dtx->CurTime);
/* draw_tick_marks( dtx ); */
end_aa_pass(i);
}
}
clipping_on();
render_3d_only( dtx, animflag );
clipping_off();
if (dtx->DisplayClips){
render_vclips( dtx, animflag );
render_hclips( dtx, animflag );
}
}
/*** Draw 2-D objects ***/
set_2d();
render_2d_only( dtx );
/*** Draw Sounding ***/
render_sounding_only( dtx , 0);
if (dtx->AnimRecord) {
save_frame( dtx, dtx->CurTime );
}
finish_rendering();
}
syntax highlighted by Code2HTML, v. 0.9.1