home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
p
/
pdraw.zip
/
PDRAW.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-23
|
89KB
|
3,064 lines
#ifdef SCCS
static char sccsid[]="%W% Oki Electric Industry Co., Ltd. %E%";
#endif
/*
* Copyright (c) 1991 by Stardent Computer Inc.
* Copyright (c) 1992 by
* Oki Electric Industry Co., Ltd.
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Oki not be
* used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission. Oki
* makes no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*************************************************************************
*
* P D R A W
*
* A PEX/PHIGS drawing program, Version 1.2 entirely Motif based.
*
* I expect that version 2.0 will still use Motif, but it will use Wcl
* to create the widgets, instead of UIL. It will also use Tcl.
*
* This program was prepared for the tutorial PEX Programming: A mixture of
* PHIGS, X and Motif, given at the Sixth Annual X Technical Conference,
* January 1992, by Jan Hardenbergh.
* Version 1.2 has the surface form, added for SIGGRAPH 92.
*
* The files you will need for Version 1.0 are:
* pdraw.c - this file. This contains all source (so much for modularity)
* pdraw.uil - The UI description for this program.
* pdraw.man - the manual page for pdraw - not much, but something.
* Imakefile - with micro make included.
*
*
*************************************************************************/
#define NO_TRANS 1 /* this enables transparency for Oki machines */
#include <stdlib.h> /* for strtod() */
#include <stdio.h>
#include <Xm/Xm.h> /* Motif Toolkit */
#include <Mrm/MrmPublic.h> /* Mrm */
#include <Xm/ToggleB.h> /* for XmToggleButtonGetState() */
#include <X11/Xatom.h>
#include <math.h>
#include <phigs/phigs.h>
/*************************************************************************
* typedefs.
*/
typedef struct {
Ppoint3 point;
Pvec3 offset;
Pvec3 scale;
Pfloat x_ang;
Pfloat y_ang;
Pfloat z_ang;
Pfloat delta_x;
Pfloat delta_y;
Pfloat delta_z;
Pint strux_id;
Pint wk_id;
Display *dpy;
int stop;
} SpinInfo;
/*
* other business
*/
#if defined(SVR4_0) || defined(SVR4) || defined(hpux)
#include <string.h>
#define bcopy(b1,b2,len) memmove(b2, b1, len)
#define bzero(b,len) memset(b, 0, len)
#define bcmp(b1,b2,len) memcmp(b1, b2, len)
#endif
#ifndef MAXFLOAT
#define MAXFLOAT 10000000.0
#endif
/*************************************************************************
*
* F U N C T I O N P R O T O T Y P E S
*
*/
static int applyViewSet(int viewNumber);
static int getNumberWidgetValue(int id, float *value);
static int setNumberWidgetValue(int id, float value);
void InsertLine( long strux, Ppoint_list3 *points, int select );
int Map2Points( int wkid, int firstX, int firstY, int secondX, int secondY,
Ppoint_list3 *points );
void ResizeWorkstation(long wkid, int width, int height);
void PickSomething( long wkid, int x, int y, long *struxID, long *elem);
void SelectSomething( long strux, long element );
void ClearSelection();
void DumpStrux(long strux, long element, int pretty );
void PrintElement( long struxID, long element, Pelem_type eType, long eSize,
Pelem_data *data );
void InitStrux( long strux );
void TranslateSelected( Ppoint_list3 *points );
void DeleteSelected();
void InsertTriStrip( long strux, Ppoint_list3 *points, int select );
int MapPoints( int wkid, Ppoint_list3 *points );
static void RotateObject(long wkid, long struxid, long count);
static void StartSpinning(long wkid, long struxid, long count);
Boolean oneSpin(char *client_data);
static void StopSpinning(long wkid);
static GC CreateDynGC(Widget drawArea);
static int GetXPointsFromSelected(int *count, XPoint **points);
static int MapWcPointsToX( int wkid, int view, Ppoint_list3 *wcPoints,
XPoint *xPoints );
static void DeleteAllStrux();
static void MyPHIGSErrorHandler( Pint errnum, Pint funcnum, char *fname);
static void build_sphere(long struxID);
static void ApplySurfaceAttrs();
/*
* event handler
*/
static void motionHandler( Widget widget, XtPointer unused,
XMotionEvent *event, Boolean *continue_to_dispatch);
static void set_tool_pointer();
static void set_tool_line();
static void set_tool_view();
static void set_tool_tristrip();
#define RADIAN(x) ((x)*(3.1415927 / 180.0))
/*************************************************************************
*
* G L O B A L V A R I A B L E S
*
*/
static float theDepth = 0.5;
static Pmatrix3 theMatOri, theMatMap;
static SpinInfo theSpinInfo;
static Pint thePHIGSWorkstation = 1;
static MrmHierarchy theMrmHierarchy; /* MRM database hierarchy ID */
int theAnchorX, theAnchorY, theDynX, theDynY, theAltX, theAltY;
int theTriStripCount = 0;
GC theDynGC = NULL;
#define TRIMAX 12
Ppoint3 theTriPoints[TRIMAX];
float theTheta, thePhi, theDeltaTheta, theDeltaPhi;
int thedebug;
#define LIGHTMAX 8
int act[LIGHTMAX], deact[LIGHTMAX];
Pint_list theLightsON = {0,act}; /* activation list */
Pint_list theLightsOFF = {0,deact}; /* deactivation list */
#define TOOL_POINTER 1
#define TOOL_LINE 2
#define TOOL_VIEW 3
#define TOOL_TRISTRIP 4
static int theCurrentTool = TOOL_LINE;
#define SELECT_COLOR_IND 3
static int theCurrentLineIndex = 1;
#define INT_STYLE_ELEM 3
#define REFL_EQN_ELEM 4
#define REFL_PROPS_ELEM 5
#define INT_SHAD_ELEM 6
#define LIGHT_SRC_ELEM 7
#define MATRIX_ELEM 8
#define FACE_CULL_MODE 9
int theCullMode = (int)PCULL_NONE;
int theShadeMode = (int)PSD_NONE;
int theSolidMode = (int)PSTYLE_HOLLOW;
static long theNewStrux = 0;
Pstore thePHIGSStore = (Pstore)0;
static int theUQUMFlag = 0;
static Pint thePHIGSError = 0;
static long theSelectedStrux, theSelectedElement = -1;
/*
* stretch selected stuff
*/
static long theSelectedIndex; /* which point in list */
XtAppContext theAppContext;
static Widget theDrawingArea = NULL, /* the PEX area */
theViewForm = NULL, /* the View Paramter Form */
theLightForm = NULL, /* the Light Form */
theSurfaceForm = NULL, /* the Surface Form */
theTopLevel = NULL, /* global parent */
theFileForm = NULL; /* archive file handler */
#define MAX_WIDGET 120
static Widget widgetArray[MAX_WIDGET];
/*************************************************************************
*
* D Y N A M I C F E E D B A C K R O U T I N E S
*
*/
static void fbInitLine( XButtonPressedEvent *event );
static void fbDynLine( XMotionEvent *event );
static void fbEndLine( XButtonReleasedEvent *event );
static void fbDummy();
static void fbEndPick( XButtonReleasedEvent *event );
static void fbInitTriStrip( XButtonPressedEvent *event );
static void fbDynTriStrip( XMotionEvent *event );
static void fbEndTriStrip( XButtonReleasedEvent *event );
static void fbFinishTriStrip ( XButtonReleasedEvent *event );
static void fbInitView( XButtonPressedEvent *event );
static void fbDynView( XMotionEvent *event );
static void fbEndView( XButtonReleasedEvent *event );
static void fbInitTranslate( XButtonPressedEvent *event );
/* use dynline */
static void fbEndTranslate( XButtonReleasedEvent *event );
static void fbInitStretch( XButtonPressedEvent *event );
/* use dynline, or dyntristrip */
static void fbEndStretch( XButtonReleasedEvent *event );
/*
* input dispatch tables
*/
typedef void (*pdrawHandler)();
static pdrawHandler thePressHandlerTable[3] =
{ fbInitLine, fbInitLine, fbInitLine };
static pdrawHandler theMotionHandlerTable[3] =
{ fbDynLine, fbDynLine, fbDynLine };
static pdrawHandler theReleaseHandlerTable[3] =
{ fbEndLine, fbEndLine, fbEndLine };
typedef int (*pdrawCmd)();
static int ReadArchiveFile(char *filename);
static int WriteArchiveFile(char *filename);
static pdrawCmd theFileCmd = { ReadArchiveFile };
/* forward declaration of interface procedures */
static void proc_pdraw_create();
static void proc_pdraw_expose();
static void proc_pdraw_resize();
static void proc_pdraw_input();
static void proc_pdraw_exit();
static void proc_pdraw_activate();
static void proc_pdraw_file();
/* binding of uil procedure names with C functions */
static MRMRegisterArg regvec[] = {
{"proc_pdraw_exit",(caddr_t)proc_pdraw_exit},
{"proc_pdraw_create",(caddr_t)proc_pdraw_create},
{"proc_pdraw_expose",(caddr_t)proc_pdraw_expose},
{"proc_pdraw_resize",(caddr_t)proc_pdraw_resize},
{"proc_pdraw_input",(caddr_t)proc_pdraw_input},
{"proc_pdraw_activate",(caddr_t)proc_pdraw_activate},
{"proc_pdraw_file",(caddr_t)proc_pdraw_file}
};
static MrmCount regnum = sizeof(regvec) / sizeof(MRMRegisterArg);
/*************************************************************************
*
* C O N S T A N T S U S E D B Y U I L
*
*
* why the &^%&^% these are not generated by UIL!.
*
*/
#define k_drawing_area 0
#define k_view_set 1
#define k_apply_vs 2
#define k_reset_vs 3
#define k_dismiss_vs 4
#define k_view_ref_pt_x 5
#define k_view_ref_pt_y 6
#define k_view_ref_pt_z 7
#define k_view_pl_norm_x 8
#define k_view_pl_norm_y 9
#define k_view_pl_norm_z 10
#define k_view_up_vect_x 11
#define k_view_up_vect_y 12
#define k_view_up_vect_z 13
#define k_proj_ref_pt_x 14
#define k_proj_ref_pt_y 15
#define k_proj_ref_pt_z 16
#define k_view_window_minx 17
#define k_view_window_maxx 18
#define k_view_window_miny 19
#define k_view_window_maxy 20
#define k_view_plane_dist 21
#define k_view_plane_back 22
#define k_view_plane_front 23
#define k_proj_vp_minx 24
#define k_proj_vp_maxx 25
#define k_proj_vp_miny 26
#define k_proj_vp_maxy 27
#define k_proj_vp_minz 28
#define k_proj_vp_maxz 29
#define k_proj_type_para 30
#define k_proj_type_persp 31
#define k_dump_strux 32
#define k_refresh 33
#define k_tool_pointer 34
#define k_tool_line 35
#define k_tool_view 36
#define k_tool_tristrip 37
#define k_delete 38
#define k_light 39
#define k_light_on1 40
#define k_light_on2 41
#define k_light_on3 42
#define k_light_on4 43
#define k_light_on5 44
#define k_light_on6 45
#define k_light_on7 46
#define k_light_on8 47
#define k_light_edit1 48
#define k_light_edit2 49
#define k_light_edit3 50
#define k_light_edit4 51
#define k_light_edit5 52
#define k_light_edit6 53
#define k_light_edit7 54
#define k_light_edit8 55
#define k_light_type_ambient 56
#define k_light_type_directional 57
#define k_light_type_positional 58
#define k_light_type_spot 59
#define k_light_pos_x 60
#define k_light_pos_y 61
#define k_light_pos_z 62
#define k_light_color_red 63
#define k_light_color_green 64
#define k_light_color_blue 65
#define k_light_direction_x 66
#define k_light_direction_y 67
#define k_light_direction_z 68
#define k_light_coeff_const 69
#define k_light_coeff_dist 70
#define k_light_conc_exp 71
#define k_light_spread_angle 72
#define k_apply_light 73
#define k_reset_light 74
#define k_dismiss_light 75
#define k_surface 76
#define k_FREE 77
#define k_spin_strux 78
#define k_spin_slowly 79
#define k_save 80
#define k_read 81
#define k_file 82
#define k_undo 83
#define k_file_help 84
#define k_delete_all 85
#define k_face_cull 86
#define k_sphere 87
#define k_dismiss_surface 88
#define k_reset_surface 89
#define k_apply_surface 90
#define k_surface_refl_transparency 91
#define k_surface_refl_specexp 92
#define k_surface_refl_specular 93
#define k_surface_refl_diffuse 94
#define k_surface_refl_ambient 95
#define k_sstyle_empty 96
#define k_sstyle_solid 97
#define k_sstyle_hollow 98
#define k_sshade_flat 99
#define k_sshade_gouraud 100
#define k_sshade_dot 101
#define k_sshade_phong 102
#define k_cull_none 103
#define k_cull_back 104
#define k_cull_front 105
/*
* number strings
*/
static char *numberStrings[] = {
"", /* k_drawing_area 0 */
"", /* k_view_set 1 */
"", /* k_apply_vs 2 */
"", /* k_reset_vs 3 */
"", /* k_dismiss_vs 4 */
"view_ref_pt_x", /* k_view_ref_pt_x 5 */
"view_ref_pt_y", /* k_view_ref_pt_y 6 */
"view_ref_pt_z", /* k_view_ref_pt_z 7 */
"view_pl_norm_x", /* k_view_pl_norm_x 8 */
"view_pl_norm_y", /* k_view_pl_norm_y 9 */
"view_pl_norm_z", /* k_view_pl_norm_z 10 */
"view_up_vect_x", /* k_view_up_vect_x 11 */
"view_up_vect_y", /* k_view_up_vect_y 12 */
"view_up_vect_z", /* k_view_up_vect_z 13 */
"view_window_minx", /* k_view_window_minx 17 */
"view_window_maxx", /* k_view_window_maxx 18 */
"view_window_miny", /* k_view_window_miny 19 */
"view_window_maxy", /* k_view_window_maxy 20 */
"view_plane_dist", /* k_view_plane_dist 21 */
"view_plane_back", /* k_view_plane_back 22 */
"view_plane_front", /* k_view_plane_front 23 */
"proj_vp_minx", /* k_proj_vp_minx 24 */
"proj_vp_maxx", /* k_proj_vp_maxx 25 */
"proj_vp_miny", /* k_proj_vp_miny 26 */
"proj_vp_maxy", /* k_proj_vp_maxy 27 */
"proj_vp_minz", /* k_proj_vp_minz 28 */
"proj_vp_maxz", /* k_proj_vp_maxz 29 */
"proj_type_para", /* k_proj_type_para 30 */
"proj_type_persp", /* k_proj_type_persp 31 */
"dump_strux", /* k_dump_strux 32 */
"refresh", /* k_refresh 33 */
"tool_pointer", /* k_tool_pointer 34 */
"tool_line", /* k_tool_line 35 */
"tool_view", /* k_tool_view 36 */
"tool_tristrip", /* k_tool_tristrip 37 */
"delete", /* k_delete 38 */
"light", /* k_light 39 */
"light_on1", /* k_light_on1 40 */
"light_on2", /* k_light_on2 41 */
"light_on3", /* k_light_on3 42 */
"light_on4", /* k_light_on4 43 */
"light_on5", /* k_light_on5 44 */
"light_on6", /* k_light_on6 45 */
"light_on7", /* k_light_on7 46 */
"light_on8", /* k_light_on8 47 */
"light_edit1", /* k_light_edit1 48 */
"light_edit2", /* k_light_edit2 49 */
"light_edit3", /* k_light_edit3 50 */
"light_edit4", /* k_light_edit4 51 */
"light_edit5", /* k_light_edit5 52 */
"light_edit6", /* k_light_edit6 53 */
"light_edit7", /* k_light_edit7 54 */
"light_edit8", /* k_light_edit8 55 */
"light_type_ambient", /* k_light_type_ambient 56 */
"light_type_directional", /* k_light_type_directional 57 */
"light_type_positional", /* k_light_type_positional 58 */
"light_type_spot", /* k_light_type_spot 59 */
"light_pos_x", /* k_light_pos_x 60 */
"light_pos_y", /* k_light_pos_y 61 */
"light_pos_z", /* k_light_pos_z 62 */
"light_color_red", /* k_light_color_red 63 */
"light_color_green", /* k_light_color_green 64 */
"light_color_blue", /* k_light_color_blue 65 */
"light_direction_x", /* k_light_direction_x 66 */
"light_direction_y", /* k_light_direction_y 67 */
"light_direction_z", /* k_light_direction_z 68 */
"light_coeff_const", /* k_light_coeff_const 69 */
"light_coeff_dist", /* k_light_coeff_dist 70 */
"light_conc_exp", /* k_light_conc_exp 71 */
"light_spread_angle", /* k_light_spread_angle 72 */
"apply_light", /* k_apply_light 73 */
"reset_light", /* k_reset_light 74 */
"dismiss_light", /* k_dismiss_light 75 */
"surface", /* k_surface 76 */
"FREE", /* k_FREE 77 */
"spin_strux", /* k_spin_strux 78 */
"spin_slowly", /* k_spin_slowly 79 */
"save", /* k_save 80 */
"read", /* k_read 81 */
"file", /* k_file 82 */
"undo", /* k_undo 83 */
"file_help", /* k_file_help 84 */
"delete_all", /* k_delete_all 85 */
"face_cull", /* k_face_cull 86 */
"sphere", /* k_sphere 87 */
"dismiss_surface", /* k_dismiss_surface 88 */
"reset_surface", /* k_reset_surface 89 */
"apply_surface", /* k_apply_surface 90 */
"surface_refl_transparency", /* k_surface_refl_transparency 91 */
"surface_refl_specexp", /* k_surface_refl_specexp 92 */
"surface_refl_specular", /* k_surface_refl_specular 93 */
"surface_refl_diffuse", /* k_surface_refl_diffuse 94 */
"surface_refl_ambient", /* k_surface_refl_ambient 95 */
"sstyle_empty", /* k_sstyle_empty 96 */
"sstyle_solid", /* k_sstyle_solid 97 */
"sstyle_hollow", /* k_sstyle_hollow 98 */
"sshade_flat", /* k_sshade_flat 99 */
"sshade_gouraud", /* k_sshade_gouraud 100 */
"sshade_dot", /* k_sshade_dot 101 */
"sshade_phong", /* k_sshade_phong 102 */
"cull_none", /* k_cull_none 103 */
"cull_back", /* k_cull_back 104 */
"cull_front" /* k_cull_front 105 */
};
static int numberStringCount = sizeof(numberStrings) / sizeof(char *);
/******************************************************************
*
* M A I N
*/
int main(argc, argv)
int argc;
char **argv;
{
Widget pdrawmain;
Arg arglist[1];
int n;
MrmCode class;
char *files[1];
MrmInitialize ();
theTopLevel = XtAppInitialize(&theAppContext, "pdraw",
(XrmOptionDescList)NULL , 0,
(Cardinal*)&argc, (String*)argv,
(String*)NULL, (ArgList)NULL, 0);
/*
* Open the User Interface Description file.
* pdraw.uil is compiled into pdraw.uid
*/
files[0] = "pdraw.uid";
if (MrmOpenHierarchy( 1, files, NULL, &theMrmHierarchy) != MrmSUCCESS) {
printf ("can't open pdraw.uid\n");
exit(0);
}
if (MrmRegisterNames (regvec, regnum) != MrmSUCCESS) {
printf("can't register names\n");
exit(0) ;
}
if (MrmFetchWidget (theMrmHierarchy, "pdraw_obj_main",
theTopLevel, &pdrawmain, &class)
!= MrmSUCCESS) {
printf("can't fetch interface\n");
exit(0);
}
XtManageChild(pdrawmain);
XtRealizeWidget(theTopLevel);
/*
* Init PHIGS and other boring stuff.
*/
InitPHIGS();
XtAppMainLoop(theAppContext); /* Hand over control to the UI & User */
}
/*************************************************************************
* InitPHIGS
*
* Open PHIGS using popen_xphigs
*/
InitPHIGS()
{
Pxphigs_info info;
Pconnid_x_drawable connid;
long i = 0;
Pint struxid = 1;
Ppoint3 p[6], *pp;
Ppoint_list3 plist;
Pint wsType = 0;
void (*perr_hand)(); /* this will be perr_hand, so no need to save it */
XWindowAttributes winAttrs;
VisualID visualID;
XStandardColormap *scm;
Atom myAtom;
char atomName[80];
int count;
info.display = XtDisplay(theDrawingArea);
info.flags.no_monitor = 1;
popen_xphigs( NULL, 0, PXPHIGS_INFO_DISPLAY | PXPHIGS_INFO_FLAGS_NO_MON,
&info );
/*
* try to create a workstation that uses a RGB_DEFAULT_MAP colormap.
* this will prevent color flashing ( technicolor )
*/
XGetWindowAttributes(XtDisplay(theDrawingArea),XtWindow(theDrawingArea),
&winAttrs);
visualID = XVisualIDFromVisual(winAttrs.visual);
if (XGetRGBColormaps(XtDisplay(theDrawingArea),
RootWindow(XtDisplay(theDrawingArea),
XScreenNumberOfScreen(winAttrs.screen)),
&scm, &count, XA_RGB_DEFAULT_MAP )) {
printf("have a RGB_DEFAULT_MAP = count = %d\n", count );
for (i = 0; i < count; i++, scm++ ) {
if ( scm->visualid == visualID ) {
printf("got a match\n");
sprintf (atomName, "RGB_PEX_MAP_%d", visualID);
myAtom = XInternAtom( XtDisplay(theDrawingArea), atomName, False );
XChangeProperty(XtDisplay(theDrawingArea),
RootWindow(XtDisplay(theDrawingArea),
XScreenNumberOfScreen(winAttrs.screen)),
myAtom, XA_RGB_COLOR_MAP, 32, PropModeReplace,
(unsigned char *)scm, sizeof(XStandardColormap)/4 );
wsType = phigs_ws_type_create( phigs_ws_type_x_drawable,
PHIGS_X_CMAP_PROP_ATOM, (char *)myAtom,
PHIGS_X_BUF_MODE, PHIGS_BUF_DOUBLE,
NULL );
break;
}
}
}
/*
* create a workstation that is output only, double buffers, at the least.
*/
if (wsType == 0 )
wsType = phigs_ws_type_create( phigs_ws_type_x_drawable,
PHIGS_X_BUF_MODE, PHIGS_BUF_DOUBLE,
NULL );
/*
* open a PHIGS workstation in the drawing area.
*/
connid.display = XtDisplay(theDrawingArea);
connid.drawable_id = XtWindow(theDrawingArea);
popen_ws(thePHIGSWorkstation, (Pconnid)&connid, wsType );
pset_hlhsr_mode(thePHIGSWorkstation, PHIGS_HLHSR_MODE_ZBUFF);
pset_disp_upd_st(thePHIGSWorkstation, PDEFER_WAIT, PMODE_NIVE );
/*
* we want to work in view 1, so when points get mapped make sure they
* have a preference for view 1.
*/
pset_view_tran_in_pri(thePHIGSWorkstation, 1, 0, PPRI_HIGHER );
/*
* Just turn some lights on for the heck of it.
*/
InitLights(thePHIGSWorkstation);
popen_struct(struxid);
pset_view_ind(1);
pset_linewidth(3.0);
plist.points = p;
pp = (Ppoint3 *)p;
pp->x = 0.5; pp->y = 0.0; pp->z = 0.0; pp++;
pp->x = 1.0; pp->y = 1.0; pp->z = 0.0; pp++;
pp->x = 0.5; pp->y = 0.0; pp->z = 1.0; pp++;
pp->x = 0.5; pp->y = 0.0; pp->z = -1.0; pp++;
pp->x = 0.5; pp->y = 1.0; pp->z = -1.0; pp++;
pp->x = 1.0; pp->y = 0.0; pp->z = 0.0;
plist.num_points = 6;
ppolyline3( &plist );
pclose_struct();
ppost_struct (thePHIGSWorkstation, struxid, 0.0);
applyViewSet(1);
predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
theDynGC = CreateDynGC(theDrawingArea);
theSpinInfo.stop = 1;
thePHIGSError = 0; /* see MyPHIGSErrorHandler */
pset_err_hand( &MyPHIGSErrorHandler, &perr_hand);
}
/*************************************************************************
*
* U S E R I N T E R F A C E C A L L B A C K S
*
* All UI callbacks are also defined in pdraw.uil and begin proc_pdraw_??
*
*/
static void proc_pdraw_create( widget, tag, cbData )
Widget widget;
int *tag;
XmAnyCallbackStruct *cbData;
{
Arg arg ;
int which = *(int *)tag;
switch (which) {
case k_drawing_area:
theDrawingArea = widget;
XtAddEventHandler( theDrawingArea, ButtonMotionMask, FALSE, motionHandler, NULL );
break;
case k_view_set:
theViewForm = widget;
break;
case k_light:
theLightForm = widget;
break;
case k_file:
theFileForm = widget;
break;
default:
if (which > MAX_WIDGET) {
printf(" got widget #%d, MAX is still %d\n",which,MAX_WIDGET);
return;
}
widgetArray[which] = widget;
break;
}
}
static void proc_pdraw_expose( widget, tag, cbData )
Widget widget;
int *tag;
XmAnyCallbackStruct *cbData;
{
predraw_all_structs( thePHIGSWorkstation, PFLAG_ALWAYS );
}
static void proc_pdraw_resize( widget, tag, cbData )
Widget widget;
int *tag;
XmAnyCallbackStruct *cbData;
{
XWindowAttributes winAttrs;
/*
* I'm positive this is a terrible hack in violation of all of Xt
* rules and regulations, but event was not comming back in call_back data.
*/
XGetWindowAttributes(XtDisplay(theDrawingArea), XtWindow(theDrawingArea),
&winAttrs );
ResizeWorkstation( thePHIGSWorkstation, winAttrs.width, winAttrs.height );
predraw_all_structs( thePHIGSWorkstation, PFLAG_ALWAYS );
}
static void proc_pdraw_input( widget, tag, cbData )
Widget widget;
int *tag;
XmAnyCallbackStruct *cbData;
{
XEvent *event = cbData->event;
if (event->xbutton.button < 1 || event->xbutton.button > 3) return;
if (event->type == ButtonPress) {
thePressHandlerTable[event->xbutton.button-1](event);
} else if (event->type == ButtonRelease) {
theReleaseHandlerTable[event->xbutton.button-1](event);
}
}
static void proc_pdraw_exit( widget, tag, cbData )
Widget widget;
char *tag;
XmAnyCallbackStruct *cbData;
{
exit(0);
}
/*************************************************************************
*
* P R O C _ P D R A W _ A C T I V A T E
*/
static void proc_pdraw_activate( widget, tag, cbData )
Widget widget;
char *tag;
XmAnyCallbackStruct *cbData;
{
int which = *(int *)tag;
MrmCode class;
switch (which) {
case k_view_set:
if (theViewForm == NULL) { /* The first time, fetch order box. */
if (MrmFetchWidget(theMrmHierarchy, "file_dialog", theTopLevel,
&theViewForm, &class) != MrmSUCCESS) {
printf("can't fetch order box widget");
return;
}
}
if (XtIsManaged(theViewForm))
XtUnmanageChild(theViewForm);
else
XtManageChild(theViewForm);
break;
case k_apply_vs:
applyViewSet(1);
break;
case k_reset_vs:
break;
case k_dismiss_vs:
XtUnmanageChild(theViewForm);
break;
case k_dump_strux:
if ( theSelectedElement != -1 ) {
DumpStrux(theSelectedStrux, -1, 1 );
} else {
DumpStrux(theNewStrux, -1, 1 );
}
break;
case k_refresh:
predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
break;
case k_tool_pointer:
set_tool_pointer();
break;
case k_tool_line:
set_tool_line();
break;
case k_tool_view:
set_tool_view();
break;
case k_tool_tristrip:
set_tool_tristrip();
break;
case k_delete:
DeleteSelected();
predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
break;
case k_light:
if (theLightForm == NULL) { /* The first time, fetch order box. */
if (MrmFetchWidget(theMrmHierarchy, "light_dialog", theTopLevel,
&theLightForm, &class) != MrmSUCCESS) {
printf("can't fetch light form widget");
return;
}
}
if (XtIsManaged(theLightForm))
XtUnmanageChild(theLightForm);
else
XtManageChild(theLightForm);
break;
case k_apply_light:
break;
case k_reset_light:
break;
case k_dismiss_light:
XtUnmanageChild(theLightForm);
break;
case k_surface:
if (theSurfaceForm == NULL) { /* The first time, fetch order box. */
if (MrmFetchWidget(theMrmHierarchy, "surface_dialog", theTopLevel,
&theSurfaceForm, &class) != MrmSUCCESS) {
printf("can't fetch surface form widget");
return;
}
}
if (XtIsManaged(theSurfaceForm))
XtUnmanageChild(theSurfaceForm);
else
XtManageChild(theSurfaceForm);
break;
case k_apply_surface:
ApplySurfaceAttrs();
predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
break;
case k_reset_surface:
break;
case k_dismiss_surface:
XtUnmanageChild(theSurfaceForm);
break;
#if 0
case 9999:
if ( ++theSolidMode > (int)PSTYLE_SOLID )
theSolidMode = (int)PSTYLE_HOLLOW;
if ( theSelectedElement != -1 ) {
ChangeStruxAttr( theSelectedStrux, INT_STYLE_ELEM, theSolidMode );
} else {
ChangeStruxAttr( theNewStrux, INT_STYLE_ELEM, theSolidMode );
}
predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
break;
case 9998:
/* really should inquire what methods are available!!! */
if ( ++theShadeMode > (int)PSD_COLOUR ) theShadeMode = (int)PSD_NONE;
if ( theSelectedElement != -1 ) {
ChangeStruxAttr( theSelectedStrux, INT_SHAD_ELEM, theShadeMode );
} else {
ChangeStruxAttr( theNewStrux, INT_SHAD_ELEM, theShadeMode );
}
predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
break;
case 9997:
if ( ++theCullMode > (int)PCULL_FRONTFACE ) theCullMode = (int)PCULL_NONE;
if ( theSelectedElement != -1 ) {
ChangeStruxAttr( theSelectedStrux, FACE_CULL_MODE, theCullMode );
} else {
ChangeStruxAttr( theNewStrux, FACE_CULL_MODE, theCullMode );
}
predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
break;
#endif
case k_spin_strux:
if ( theSelectedElement != -1 ) {
RotateObject( thePHIGSWorkstation, theSelectedStrux, 20 );
} else {
RotateObject( thePHIGSWorkstation, theNewStrux, 20 );
}
break;
case k_spin_slowly:
if (!theSpinInfo.stop) {
StopSpinning( thePHIGSWorkstation );
} else {
if ( theSelectedElement != -1 ) {
StartSpinning( thePHIGSWorkstation, theSelectedStrux, 120 );
} else {
StartSpinning( thePHIGSWorkstation, theNewStrux, 120 );
}
}
break;
case k_sphere:
build_sphere(112);
predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
break;
case k_read:
case k_save:
if (theFileForm == NULL) { /* The first time, fetch order box. */
if (MrmFetchWidget(theMrmHierarchy, "file_dialog", theTopLevel,
&theFileForm, &class) != MrmSUCCESS) {
printf("can't fetch order box widget");
return;
}
}
theFileCmd = (which == k_read)?ReadArchiveFile:WriteArchiveFile;
if (XtIsManaged(theFileForm))
XtUnmanageChild(theFileForm);
else
XtManageChild(theFileForm);
break;
case k_undo:
break;
case k_file_help:
break;
case k_delete_all:
DeleteAllStrux();
break;
default:
break;
}
}
/*************************************************************************
* proc_pdraw_file
*
* handle callback fron file selection mechanism.
*/
static void proc_pdraw_file( widget, tag, cbData )
Widget widget;
char *tag;
XmFileSelectionBoxCallbackStruct *cbData;
{
char *filename;
int status;
switch (cbData->reason) {
case XmCR_OK:
case XmCR_APPLY:
if (!XmStringGetLtoR(cbData->value, XmSTRING_DEFAULT_CHARSET,
&filename )) {
printf("imagine a popup...\n");
} else {
status = theFileCmd(filename);
predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
}
if (cbData->reason == XmCR_OK) XtUnmanageChild(theFileForm);
break;
case XmCR_CANCEL:
XtUnmanageChild(theFileForm);
break;
case XmCR_HELP:
break;
default:
break;
}
}
/*************************************************************************
*
* T O O L S E L E C T I O N R O U T I N E S
*
*************************************************************************
*/
static void set_tool_pointer()
{
if (theCurrentTool != TOOL_POINTER) {
theCurrentTool = TOOL_POINTER;
/*
* don't deal with fancy pre-pick hilite, yet.
*/
thePressHandlerTable[0] = fbDummy;
theMotionHandlerTable[0] = fbDummy;
theReleaseHandlerTable[0] = fbEndPick;
thePressHandlerTable[1] = fbInitTranslate;
theMotionHandlerTable[1] = fbDynLine;
theReleaseHandlerTable[1] = fbEndTranslate;
thePressHandlerTable[2] = fbInitStretch;
theMotionHandlerTable[2] = fbDummy;
theReleaseHandlerTable[2] = fbEndStretch;
}
}
static void set_tool_line()
{
if (theCurrentTool != TOOL_LINE) {
theCurrentTool = TOOL_LINE;
thePressHandlerTable[0] = fbInitLine;
theMotionHandlerTable[0] = fbDynLine;
theReleaseHandlerTable[0] = fbEndLine;
thePressHandlerTable[1] = fbInitLine;
theMotionHandlerTable[1] = fbDynLine;
theReleaseHandlerTable[1] = fbEndLine;
thePressHandlerTable[2] = fbInitView;
theMotionHandlerTable[2] = fbDynView;
theReleaseHandlerTable[2] = fbEndView;
}
}
static void set_tool_view()
{
if (theCurrentTool != TOOL_VIEW) {
theCurrentTool = TOOL_VIEW;
thePressHandlerTable[0] = fbInitView;
theMotionHandlerTable[0] = fbDynView;
theReleaseHandlerTable[0] = fbEndView;
thePressHandlerTable[1] = fbDummy;
theMotionHandlerTable[1] = fbDummy;
theReleaseHandlerTable[1] = fbDummy;
thePressHandlerTable[2] = fbInitView;
theMotionHandlerTable[2] = fbDynView;
theReleaseHandlerTable[2] = fbEndView;
}
}
static void set_tool_tristrip()
{
if (theCurrentTool != TOOL_TRISTRIP) {
theCurrentTool = TOOL_TRISTRIP;
thePressHandlerTable[0] = fbInitTriStrip;
theMotionHandlerTable[0] = fbDynTriStrip;
theReleaseHandlerTable[0] = fbEndTriStrip;
thePressHandlerTable[1] = fbFinishTriStrip;
theMotionHandlerTable[1] = fbDummy;
theReleaseHandlerTable[1] = fbDummy;
thePressHandlerTable[2] = fbInitView;
theMotionHandlerTable[2] = fbDynView;
theReleaseHandlerTable[2] = fbEndView;
}
}
/*************************************************************************
*
* D Y N A M I C F E E D B A C K R O U T I N E S
*
*/
static void fbInitLine( XButtonPressedEvent *event )
{
XGCValues values;
if (!theDynGC) {
values.function = GXinvert;
theDynGC = XCreateGC( XtDisplay(theDrawingArea), XtWindow(theDrawingArea),
GCFunction, &values );
}
theAnchorX = event->x;
theAnchorY = event->y;
theDynX = event->x;
theDynY = event->y;
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
}
static void fbDynLine( XMotionEvent *event )
{
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
theDynX = event->x;
theDynY = event->y;
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
}
static void fbEndLine( XButtonReleasedEvent *event )
{
Ppoint_list3 points;
Ppoint3 pl[2];
points.points = pl;
if (Map2Points(thePHIGSWorkstation, theAnchorX, theAnchorY, theDynX, theDynY,
&points)) {
if (theNewStrux == 0) {
theNewStrux = 111;
InitStrux(theNewStrux);
}
InsertLine(theNewStrux, &points, 1 );
if (!theUQUMFlag) predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
}
}
/*
* no dynamic hiliting
*/
static void fbDummy() {}
static void fbEndPick( XButtonReleasedEvent *event )
{
long s, e;
XDrawPoint( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
event->x, event->y );
if ( theSelectedElement != -1 ) ClearSelection();
PickSomething( thePHIGSWorkstation, event->x, event->y, &s, &e);
if ( e != -1 )
SelectSomething( s, e );
if (!theUQUMFlag) predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
}
/*************************************************************************
* fbInitTriStrip - initialze and reinit tristrip inster dynamics.
*
* if we are working on a tristrip, then start the next point. Otherwise,
* we are just drawing a line!
*/
static void fbInitTriStrip( XButtonPressedEvent *event )
{
if (theTriStripCount) {
if (theTriStripCount == TRIMAX) {
fbFinishTriStrip( event );
return;
}
theAnchorX = theAltX;
theAnchorY = theAltY;
theAltX = theDynX;
theAltY = theDynY;
theDynX = event->x;
theDynY = event->y;
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAltX, theAltY, theDynX, theDynY );
} else {
theAnchorX = event->x;
theAnchorY = event->y;
theDynX = event->x;
theDynY = event->y;
theAltX = event->x;
theAltY = event->y;
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
}
}
static void fbDynTriStrip( XMotionEvent *event )
{
if (theTriStripCount) {
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAltX, theAltY, theDynX, theDynY );
theDynX = event->x;
theDynY = event->y;
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAltX, theAltY, theDynX, theDynY );
} else {
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
theDynX = event->x;
theDynY = event->y;
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
}
}
static void fbEndTriStrip( XButtonReleasedEvent *event )
{
if (theTriStripCount) {
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea),
theDynGC, theAnchorX, theAnchorY, theDynX, theDynY );
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea),
theDynGC, theAltX, theAltY, theDynX, theDynY );
theDynX = event->x;
theDynY = event->y;
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea),
theDynGC, theAnchorX, theAnchorY, theDynX, theDynY );
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea),
theDynGC, theAltX, theAltY, theDynX, theDynY );
theTriPoints[theTriStripCount].x = (float)theDynX;
theTriPoints[theTriStripCount].y = (float)theDynY;
theTriPoints[theTriStripCount].z = theDepth;
theTriStripCount++;
} else {
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
theDynX = event->x;
theDynY = event->y;
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
theTriPoints[0].x = (float)theAnchorX;
theTriPoints[0].y = (float)theAnchorY;
theTriPoints[0].z = theDepth;
theTriPoints[1].x = (float)theDynX;
theTriPoints[1].y = (float)theDynY;
theTriPoints[1].z = theDepth;
theTriStripCount = 2;
}
}
static void fbFinishTriStrip ( XButtonReleasedEvent *event )
{
Ppoint_list3 points;
int i;
if (theTriStripCount < 3) return;
points.num_points = theTriStripCount;
points.points = theTriPoints; /* count has equaled index so far... */
MapPoints(thePHIGSWorkstation, &points );
if ( points.num_points > 2 ) {
if (theNewStrux == 0) {
theNewStrux = 111;
InitStrux(theNewStrux);
}
InsertTriStrip( theNewStrux, &points, 1 );
if (!theUQUMFlag) predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
}
theTriStripCount = 0;
}
/*************************************************************************
*
*/
static void fbInitTranslate( XButtonPressedEvent *event )
{
if ( theSelectedElement == -1 ) {
printf("nothing selected\n");
return;
}
theAnchorX = event->x;
theAnchorY = event->y;
theDynX = event->x;
theDynY = event->y;
XDrawPoint( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY );
}
static void fbEndTranslate( XButtonReleasedEvent *event )
{
Ppoint_list3 points;
Ppoint3 pl[2];
if ( theSelectedElement == -1 ) {
printf("nothing selected\n");
return;
}
theDynX = event->x;
theDynY = event->y;
XDrawPoint( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theDynX, theDynY );
points.points = pl;
if (Map2Points(thePHIGSWorkstation, theAnchorX, theAnchorY, theDynX, theDynY,
&points)) {
TranslateSelected( &points );
if (!theUQUMFlag) predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
}
}
/*************************************************************************
*
*/
static void fbInitStretch( XButtonPressedEvent *event )
{
int i, count;
XPoint *points, *p;
float dist, currentDist;
int error;
theSelectedIndex = -1;
error = GetXPointsFromSelected(&count, &points);
if (error) {
printf("imagine a popup dialog... %d\n", error );
return;
}
currentDist = MAXFLOAT;
for (i = 0, p = points; i < count; i++, p++ ) {
/* don't bother with divide, only relative dist counts */
dist = (event->x - p->x)*(event->x - p->x) +
(event->y - p->y)*(event->y - p->y);
if (dist < currentDist) {
currentDist = dist;
theSelectedIndex = i;
}
}
if (theSelectedIndex == -1) return;
if (theSelectedIndex > 0) {
theAnchorX = points[theSelectedIndex-1].x;
theAnchorY = points[theSelectedIndex-1].y;
} else {
theAnchorX = points[theSelectedIndex+1].x;
theAnchorY = points[theSelectedIndex+1].y;
}
free(points); /* all done */
theDynX = event->x;
theDynY = event->y;
XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC,
theAnchorX, theAnchorY, theDynX, theDynY );
/*
* O.K. we're ready.
*/
theMotionHandlerTable[2] = fbDynLine;
}
/*************************************************************************
* fbEndStretch
*/
static void fbEndStretch( XButtonReleasedEvent *event )
{
Ppoint_list3 points;
Ppoint3 pl[1];
points.points = pl;
points.num_points = 1;
points.points[0].x = (float)event->x;
points.points[0].y = (float)event->y;
points.points[0].z = theDepth;
MapPoints(thePHIGSWorkstation, &points);
if ( points.num_points == 1 ) {
StretchSelected(&points);
if (!theUQUMFlag) predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
}
theMotionHandlerTable[2] = fbDummy;
}
/*************************************************************************
* motionHandler
*
* Registered for button motion, meaning when the mouse moves while the
* button is down, this routine gets called.
*/
static void motionHandler( Widget widget, XtPointer unused,
XMotionEvent *event, Boolean *continue_to_dispatch )
{
int button;
if ( event->state == Button1MotionMask ) {
button = 0;
} else if ( event->state == Button2MotionMask ) {
button = 1;
} else if ( event->state == Button3MotionMask ) {
button = 2;
} else {
printf("bad button for motion %x\n", event->state );
return;
}
theMotionHandlerTable[button](event);
*continue_to_dispatch = 1; /* tells whether to call other dispatchers */
}
/*************************************************************************
*
* A P P L I C A T I O N P R O C E D U R E S
*
*************************************************************************
*
* Still a little overlap with the selected object interactions.
*/
/*************************************************************************
* TranslateSelected - translate whatever is selected by the given vector
*/
void
TranslateSelected( Ppoint_list3 *points )
{
Pint error;
Pelem_type eType;
size_t eSize;
Pelem_data *eData;
float deltaX, deltaY, deltaZ;
Ppoint3 *p;
int i;
if ( theSelectedElement == -1 ) return;
deltaX = points->points[1].x - points->points[0].x;
deltaY = points->points[1].y - points->points[0].y;
deltaZ = points->points[1].z - points->points[0].z;
popen_struct(theSelectedStrux);
pset_elem_ptr(theSelectedElement+1); /* move to primitive */
/*
*
*/
pinq_cur_elem_type_size( &error, &eType, &eSize );
if (error != 0) {
printf("can't inquire element type & size strux = %d, element = %d\n",
theSelectedStrux, theSelectedElement);
return;
}
if (eType == PELEM_POLYLINE3) {
if (thePHIGSStore == (Pstore)0) {
pcreate_store(&i, &thePHIGSStore);
if ( i != 0 ) printf("trouble crating store %d\n", i);
}
pinq_cur_elem_content(thePHIGSStore, &error, &eData );
if (error != 0) {
printf("can't inquire element type & size strux = %d, element = %d\n",
theSelectedStrux, theSelectedElement);
return;
}
for (i = 0; i < eData->point_list3.num_points; i++ ) {
eData->point_list3.points[i].x = eData->point_list3.points[i].x + deltaX;
eData->point_list3.points[i].y = eData->point_list3.points[i].y + deltaY;
eData->point_list3.points[i].z = eData->point_list3.points[i].z + deltaZ;
}
poffset_elem_ptr(1);
ppolyline3(&eData->point_list3);
ppolymarker3(&eData->point_list3);
poffset_elem_ptr(-2);
pdel_elem();
pdel_elem();
} else if (eType == PELEM_TRI_STRIP3_DATA) {
} else {
printf("imagine a Motif alarm! selecting unknown element type %d, %d\n",
eType, eSize );
return;
}
pclose_struct();
}
/*************************************************************************
* StretchSelected
*/
StretchSelected(Ppoint_list3 *points)
{
Pint error;
Pelem_type eType;
size_t eSize;
Pelem_data *eData;
int i;
Ppoint_list3 pts;
popen_struct(theSelectedStrux);
pset_elem_ptr(theSelectedElement+1); /* it's selected so move up 1 */
pinq_cur_elem_type_size( &error, &eType, &eSize );
if (error != 0) {
printf("can't inquire elem type&size error %d strux = %d, element = %d\n",
error, theSelectedStrux, theSelectedElement);
return (error);
}
if (thePHIGSStore == (Pstore)0) {
pcreate_store(&i, &thePHIGSStore);
if ( i != 0 ) printf("trouble crating store %d\n", i);
return (900);
}
pinq_cur_elem_content(thePHIGSStore, &error, &eData );
if (error != 0) {
printf("can't inquire element content, error = %d\n", error );
return (error);
}
pset_edit_mode(PEDIT_REPLACE);
if (eType == PELEM_POLYLINE3) {
if (theSelectedIndex < eData->point_list3.num_points) {
eData->point_list3.points[theSelectedIndex] = points->points[0];
}
ppolyline3((Ppoint_list3 *)eData);
poffset_elem_ptr(1);
ppolymarker3((Ppoint_list3 *)eData); /* got to move the fluvii, too */
} else if (eType == PELEM_TRI_STRIP3_DATA) {
/* should check to make sure there are no normals!!! */
if (theSelectedIndex < eData->tsd3.nv) {
eData->tsd3.vdata.points[theSelectedIndex] = points->points[0];
}
ptri_strip3_data(eData->tsd3.fflag, eData->tsd3.vflag,
eData->tsd3.colr_model, eData->tsd3.nv,
(Pfacet_data_arr3 *)eData->tsd3.fdata.norms,
(Pfacet_vdata_arr3 *)&eData->tsd3.vdata.points);
poffset_elem_ptr(1);
pts.num_points = eData->tsd3.nv;
pts.points = eData->tsd3.vdata.points;
ppolymarker3(&pts);
} else {
printf("imagine a Motif alarm! selecting unknown element type %d, %d\n",
eType, eSize );
}
pclose_struct();
pset_edit_mode(PEDIT_INSERT);
}
/*************************************************************************
* PickSomething - returns structure and element, else element == -1
*/
void
PickSomething( long wkid, int x, int y, long *struxID, long *elem)
{
Pescape_in_data pickData;
Pescape_out_data *outData;
int names[2];
int i;
printf("\n\n going to pick xcoords %d,%d\n",x,y);
pickData.escape_in_u4.ws_id = wkid;
pickData.escape_in_u4.point.x = x;
pickData.escape_in_u4.point.y = y;
pickData.escape_in_u4.ap_size = 5.0;
pickData.escape_in_u4.order = PORDER_TOP_FIRST;
pickData.escape_in_u4.depth = 10;
pickData.escape_in_u4.pet = 1;
pickData.escape_in_u4.echo_switch = PSWITCH_ECHO;
pickData.escape_in_u4.echo_volume.x_min = 0.0;
pickData.escape_in_u4.echo_volume.x_max = 999.0;
pickData.escape_in_u4.echo_volume.y_min = 0.0;;
pickData.escape_in_u4.echo_volume.y_max = 999.0;
pickData.escape_in_u4.echo_volume.z_min = 0.0;
pickData.escape_in_u4.echo_volume.z_max = 999.0;
names[0] = 1;
names[1] = 2;
pickData.escape_in_u4.filter.incl_set.num_ints = 2;
pickData.escape_in_u4.filter.incl_set.ints = names;
pickData.escape_in_u4.filter.excl_set.num_ints = 0;
if (thePHIGSStore == (Pstore)0) {
pcreate_store(&i, &thePHIGSStore);
if ( i != 0 ) printf("trouble crating store %d\n", i);
}
/*
* ignore DC check for echo area, pickData works iff wkid != 0
* -4 is the programmatic pick.
*/
pescape(-3, &pickData, thePHIGSStore, &outData );
pescape(-4, &pickData, thePHIGSStore, &outData );
if (outData->escape_out_u4.status == PIN_STATUS_OK) {
Ppick_path_elem *pe;
/*printf(" we got one! path depth = %d\n",outData->escape_out_u4.pick.depth);
pe = outData->escape_out_u4.pick.path_list;
for (i=0;i<outData->escape_out_u4.pick.depth;i++, pe++) {
printf(" level %d >> structure ID %d, pick_id %d, element_id %d\n",
i, pe->struct_id, pe->pick_id, pe->elem_pos );
}
*/
*struxID = outData->escape_out_u4.pick.path_list[outData->escape_out_u4.pick.depth-1].struct_id;
*elem = outData->escape_out_u4.pick.path_list[outData->escape_out_u4.pick.depth-1].elem_pos;
/* printf("that's all\n"); */
} else {
printf(" no pick, getta life\n");
*elem = -1;
}
}
/*************************************************************************
* SelectSomething( long strux, long element )
*
*/
void SelectSomething( long strux, long element )
{
Pint error;
Pelem_type eType;
size_t eSize;
Pelem_data *eData;
int i;
Ppoint_list3 points;
popen_struct(strux);
pset_elem_ptr(element);
pinq_cur_elem_type_size( &error, &eType, &eSize );
if (error != 0) {
printf("can't inquire element type & size strux = %d, element = %d\n",
strux, element);
return;
}
if (thePHIGSStore == (Pstore)0) {
pcreate_store(&i, &thePHIGSStore);
if ( i != 0 ) printf("trouble crating store %d\n", i);
}
if (eType == PELEM_POLYLINE3) {
pinq_cur_elem_content(thePHIGSStore, &error, &eData );
if (error != 0) {
printf("can't inquire element type & size strux = %d, element = %d\n",
strux, element);
return;
}
ppolymarker3((Ppoint_list3 *)eData);
poffset_elem_ptr(-2);
pset_line_colr_ind(SELECT_COLOR_IND);
pclose_struct();
} else if (eType == PELEM_TRI_STRIP3_DATA) {
pinq_cur_elem_content(thePHIGSStore, &error, &eData );
if (error != 0) {
printf("can't inquire element type & size strux = %d, element = %d\n",
strux, element);
return;
}
/* should check to make sure there are no normals!!! */
points.num_points = eData->tsd3.nv;
points.points = eData->tsd3.vdata.points;
ppolymarker3(&points);
poffset_elem_ptr(-2);
pset_int_colr_ind(SELECT_COLOR_IND);
pclose_struct();
} else {
printf("imagine a Motif alarm! selecting unknown element type %d, %d\n",
eType, eSize );
pclose_struct();
return;
}
theSelectedStrux = strux;
theSelectedElement = element;
}
/*************************************************************************
* ClearSelection
*
* Implicitly knows that each element has a color followed by a primitive
* - color
* - primitive
*
* The selected Element has an extra color between the color & prim and
* the point primitive directly afterwords. Two extra elements. This
* will be a headache if multiple elements are allowed to be selected.
*
* - color
* - select color
* - primitive
* - points.
*
* The selected color is really at theSelectedElement. Set the pointer and
* delete it. The element pointer moves forward. Skip two elements and
* delete the points.
*
*/
void ClearSelection()
{
if ( theSelectedElement == -1 ) return;
popen_struct(theSelectedStrux);
pset_elem_ptr(theSelectedElement);
pdel_elem();
poffset_elem_ptr(2);
pdel_elem();
pclose_struct();
theSelectedStrux = -1;
theSelectedElement= -1;
}
/*************************************************************************
* DeleteSelected
*/
void DeleteSelected()
{
if ( theSelectedElement == -1 ) return;
popen_struct(theSelectedStrux);
pdel_elem_range(theSelectedElement-1, theSelectedElement+2);
pclose_struct();
theSelectedStrux = -1;
theSelectedElement= -1;
}
/*************************************************************************
* InitStrux
*/
void InitStrux( long strux )
{
Pint_list names;
int int_array[2];
Pint error;
Pmatrix3 matrix;
Prefl_props reflProps;
ppost_struct(thePHIGSWorkstation, strux, 0.0);
popen_struct(strux);
/*
* need this for picking
*/
names.num_ints = 2;
names.ints = int_array;
names.ints[0] = 2;
names.ints[1] = 1;
padd_names_set(&names);
pset_view_ind(1);
pset_int_style(PSTYLE_HOLLOW); /* INT_STYLE_ELEM == element 3 */
pset_refl_eqn(PREFL_AMB_DIFF_SPEC); /* REFL_EQN_ELEM == element 4 */
/* set the area properties */
reflProps.ambient_coef = 0.3; /* ambient coefficient */
reflProps.diffuse_coef = 0.3; /* diffuse coefficient */
reflProps.specular_coef = 0.7; /* specular coefficient */
/* set specular color to white */
reflProps.specular_colr.type = PMODEL_RGB; /* specular color model */
reflProps.specular_colr.val.general.x = 1.0;
reflProps.specular_colr.val.general.y = 1.0;
reflProps.specular_colr.val.general.z = 1.0;
reflProps.specular_exp = 50.0; /* specular exponent */
pset_refl_props(&reflProps);
pset_int_shad_meth(PSD_NONE); /* INT_SHAD_ELEM == element */
theLightsON.num_ints = 2;
theLightsON.ints[0] = 1;
theLightsON.ints[1] = 2;
theLightsOFF.num_ints = 0;
pset_light_src_state(&theLightsON, &theLightsOFF); /* LIGHT_SRC_ELEM 6 */
protate_x(0.0, &error, matrix);
pset_local_tran3(matrix, PTYPE_REPLACE); /* MATRIX_ELEM 7 */
pset_face_cull_mode( PCULL_NONE );
pclose_struct();
}
/*************************************************************************
* InsertLine
*/
void InsertLine( long strux, Ppoint_list3 *points, int select )
{
Pint error, e;
if ( theSelectedElement != -1 ) ClearSelection();
/* pset_edit_mode(PEDIT_INSERT); */
popen_struct(strux);
pset_line_colr_ind(theCurrentLineIndex);
ppolyline3(points);
if (select) {
pinq_elem_ptr( &error, &e );
pclose_struct();
SelectSomething( strux, e );
} else {
pclose_struct();
}
}
/*************************************************************************
* InsertTriStrip
*/
void InsertTriStrip( long strux, Ppoint_list3 *points, int select )
{
Pint error, e;
Pfacet_vdata_arr3 vData;
if ( theSelectedElement != -1 ) ClearSelection();
popen_struct(strux);
pset_int_colr_ind(theCurrentLineIndex);
vData.points = points->points;
ptri_strip3_data(PFACET_NONE, PVERT_COORD, PMODEL_RGB, points->num_points,
(Pfacet_data_arr3 *)0, &vData);
if (select) {
pinq_elem_ptr( &error, &e );
pclose_struct();
SelectSomething( strux, e );
} else {
pclose_struct();
}
}
/*************************************************************************
* MapPoints
*/
int
MapPoints( int wkid, Ppoint_list3 *points )
{
Pescape_in_data pickData;
Pescape_out_data *outData;
int i, count;
count = points->num_points;
pickData.escape_in_u5.ws_id = wkid;
pickData.escape_in_u5.points = *points;
if (thePHIGSStore == (Pstore)0) {
pcreate_store(&i, &thePHIGSStore);
if ( i != 0 ) printf("trouble crating store %d\n", i);
}
/*
* ignore DC check for echo area, pickData works iff wkid != 0
pescape(-3, &pickData, thePHIGSStore, &outData );
*/
pescape(-5, &pickData, thePHIGSStore, &outData );
if ( outData->escape_out_u5.points.num_points != count ) {
printf("need %d points, got %d\n",
count, outData->escape_out_u5.points.num_points);
}
for (i= 0; i<outData->escape_out_u5.points.num_points; i++ ) {
points->points[i] = outData->escape_out_u5.points.points[i];
}
points->num_points = outData->escape_out_u5.points.num_points;
return (1);
}
/*************************************************************************
* Map2Points
*/
int
Map2Points( int wkid, int firstX, int firstY, int secondX, int secondY,
Ppoint_list3 *points )
{
Pescape_in_data pickData;
Pescape_out_data *outData;
int i;
points->num_points = 2;
points->points[0].x = (float)firstX;
points->points[0].y = (float)firstY;
points->points[0].z = theDepth;
points->points[1].x = (float)secondX;
points->points[1].y = (float)secondY;
points->points[1].z = theDepth;
pickData.escape_in_u5.ws_id = wkid;
pickData.escape_in_u5.points = *points;
if (thePHIGSStore == (Pstore)0) {
pcreate_store(&i, &thePHIGSStore);
if ( i != 0 ) printf("trouble crating store %d\n", i);
}
/*
* ignore DC check for echo area, pickData works iff wkid != 0
pescape(-3, &pickData, thePHIGSStore, &outData );
*/
pescape(-5, &pickData, thePHIGSStore, &outData );
if ( outData->escape_out_u5.points.num_points != 2 ) {
printf("need 2 points, got %d\n", outData->escape_out_u5.points.num_points);
return (0);
}
points->num_points = 2;
points->points[0] = outData->escape_out_u5.points.points[0];
points->points[1] = outData->escape_out_u5.points.points[1];
return (1);
}
/*************************************************************************
* MapWcPointsToX
*
* TODO:
*/
static int
MapWcPointsToX( int wkid, int view, Ppoint_list3 *wcPoints, XPoint *xPoints )
{
Ppoint3 p, q;
int i, count;
Pint error;
Pupd_st update_state;
Pview_rep3 curRep, reqRep;
Pmatrix3 orient, mapping;
Plimit3 req_win_lim, cur_win_lim;
Plimit3 req_vp_lim, cur_vp_lim;
float winWidth, winHeight, winX, winY, XX, XY;
XPoint *xp = xPoints;
float scale;
count = wcPoints->num_points;
/*
* since we do not leave view information hanging around as requested
* we won't worry about whether ther is an update pending. Just use
* the current information.
*/
/* BUG!!!
* XSync(XtDisplay(theDrawingArea), 1);
* pinq_view_rep( wkid, view, &error, &update_state, &curRep, &reqRep);
* if (error) return ((int)error);
* bcopy( (char *)&curRep.ori_matrix, (char *)&orient, sizeof(Pmatrix3));
* bcopy( (char *)&curRep.map_matrix, (char *)&mapping, sizeof(Pmatrix3));
*/
/*
* We rely on the fact that we always use the whole window for the
* Workstation viewport. Get the information we want, incase this
* scratch area gets creamed.
*/
pinq_ws_tran3( wkid, &error, &update_state, &req_win_lim, &cur_win_lim,
&req_vp_lim, &cur_vp_lim);
if (error) return ((int)error);
winWidth = cur_win_lim.x_max - cur_win_lim.x_min;
winHeight = cur_win_lim.y_max - cur_win_lim.y_min;
winX = cur_win_lim.x_min;
winY = cur_win_lim.y_min;
XX = cur_vp_lim.x_max;
XY = cur_vp_lim.y_max;
/*
* since we always maintain the workstation window and workstation viewport
* "similar" in the geometry sense, they are always isotropic. So, either
* XX/width or XY/height should be the same.
*/
scale = XX/winWidth;
for (i = 0; i < count; i++, xp++ ) {
ptran_point3(&wcPoints->points[i], theMatOri, &error, &q );
if (error) return (error);
ptran_point3(&q, theMatMap, &error, &p );
if (error) return (error);
/* OK, got an NPC point. take it to X. */
xp->x = (p.x - winX) * scale;
xp->y = XY - ((p.y - winY) * scale);
}
return (0);
}
/*************************************************************************
* GetXPointsFromSelected
*
* generate X coordinates for each vertex of the selected object.
* - inquire element contents
* - map from world [should be model] to screen using MapWCPointsToX
*
* ALLOCATES points array.
*/
static int GetXPointsFromSelected(int *count, XPoint **points)
{
Pint error;
Pelem_type eType;
size_t eSize;
Pelem_data *eData;
int i;
Ppoint_list3 wcPoints, *p;
*count = 0;
popen_struct(theSelectedStrux);
pset_elem_ptr(theSelectedElement+1); /* it's selected so move up 1 */
pinq_cur_elem_type_size( &error, &eType, &eSize );
if (error != 0) {
printf("can't inquire elem type&size error %d strux = %d, element = %d\n",
error, theSelectedStrux, theSelectedElement);
return (error);
}
if (thePHIGSStore == (Pstore)0) {
pcreate_store(&i, &thePHIGSStore);
if ( i != 0 ) printf("trouble crating store %d\n", i);
return (900);
}
pinq_cur_elem_content(thePHIGSStore, &error, &eData );
pclose_struct();
if (error != 0) {
printf("can't inquire element content, error = %d\n", error );
return (error);
}
if (eType == PELEM_POLYLINE3) {
wcPoints.num_points = eData->point_list3.num_points;
wcPoints.points = eData->point_list3.points;
} else if (eType == PELEM_TRI_STRIP3_DATA) {
wcPoints.num_points = eData->tsd3.nv;
wcPoints.points = eData->tsd3.vdata.points;
} else {
printf("trying to get points from unknown element\n");
}
*points = (XPoint *)malloc(wcPoints.num_points*sizeof(XPoint));
if (!*points) return (900);
/*
* back translate these from model to world!! Just ruined our copy.
* No we're not doing that yet.
*/
if (error = MapWcPointsToX(thePHIGSWorkstation, 1, &wcPoints, *points ))
return (error);
*count = wcPoints.num_points;
return (0);
}
/*************************************************************************
* applyViewSet - get values from widget and set the view representation
*/
static int applyViewSet(int viewNumber)
{
Ppoint3 vrp;
Pvec3 vpn;
Pvec3 vup;
Pview_rep3 vrep; /* view structure */
Pint err;
Pview_map3 view_map;
int persp;
MrmCode class;
if (theViewForm == NULL) { /* The first time, fetch order box. */
if (MrmFetchWidget(theMrmHierarchy, "view_set_dialog", theTopLevel,
&theViewForm, &class) != MrmSUCCESS) {
printf("can't fetch view set dialog");
return;
}
}
/* View Reference Point */
if (getNumberWidgetValue(k_view_ref_pt_x, &vrp.x)) return(1);
if (getNumberWidgetValue(k_view_ref_pt_y, &vrp.y)) return(1);
if (getNumberWidgetValue(k_view_ref_pt_z, &vrp.z)) return(1);
/* view plane normal */
if (getNumberWidgetValue(k_view_pl_norm_x, &vpn.delta_x)) return(1);
if (getNumberWidgetValue(k_view_pl_norm_y, &vpn.delta_y)) return(1);
if (getNumberWidgetValue(k_view_pl_norm_z, &vpn.delta_z)) return(1);
/* view up vector */
if (getNumberWidgetValue(k_view_up_vect_x, &vup.delta_x)) return(1);
if (getNumberWidgetValue(k_view_up_vect_y, &vup.delta_y)) return(1);
if (getNumberWidgetValue(k_view_up_vect_z, &vup.delta_z)) return(1);
peval_view_ori_matrix3( &vrp, &vpn, &vup,
&err, vrep.ori_matrix);
if (err != 0) { printf( "view orientation error %d\n",err); return (1); }
if (getNumberWidgetValue(k_proj_ref_pt_x, &view_map.proj_ref_point.x)) return (1);
if (getNumberWidgetValue(k_proj_ref_pt_y, &view_map.proj_ref_point.y)) return (1);
if (getNumberWidgetValue(k_proj_ref_pt_z, &view_map.proj_ref_point.z)) return (1);
if (getNumberWidgetValue(k_view_window_minx, &view_map.win.x_min)) return (1);
if (getNumberWidgetValue(k_view_window_maxx, &view_map.win.x_max)) return (1);
if (getNumberWidgetValue(k_view_window_miny, &view_map.win.y_min)) return (1);
if (getNumberWidgetValue(k_view_window_maxy, &view_map.win.y_max)) return (1);
if (getNumberWidgetValue(k_view_plane_dist, &view_map.view_plane)) return (1);
if (getNumberWidgetValue(k_view_plane_back, &view_map.back_plane)) return (1);
if (getNumberWidgetValue(k_view_plane_front, &view_map.front_plane)) return (1);
if (getNumberWidgetValue(k_proj_vp_minx, &view_map.proj_vp.x_min)) return (1);
if (getNumberWidgetValue(k_proj_vp_maxx, &view_map.proj_vp.x_max)) return (1);
if (getNumberWidgetValue(k_proj_vp_miny, &view_map.proj_vp.y_min)) return (1);
if (getNumberWidgetValue(k_proj_vp_maxy, &view_map.proj_vp.y_max)) return (1);
if (getNumberWidgetValue(k_proj_vp_minz, &view_map.proj_vp.z_min)) return (1);
if (getNumberWidgetValue(k_proj_vp_maxz, &view_map.proj_vp.z_max)) return (1);
if (widgetArray[k_proj_type_persp] == NULL) {
/* The first time, fetch order box. */
if (MrmFetchWidget(theMrmHierarchy, numberStrings[k_proj_type_persp],
theTopLevel, &widgetArray[k_proj_type_persp],
&class) != MrmSUCCESS) {
printf("can't fetch number perspective\n");
return (1);
}
}
/* View Reference Point */
persp = XmToggleButtonGetState(widgetArray[k_proj_type_persp]);
if (persp) {
view_map.proj_type = PTYPE_PERSPECT;
} else {
view_map.proj_type = PTYPE_PARAL;
}
peval_view_map_matrix3( &view_map, &err, vrep.map_matrix);
if (err != 0) { printf( "view mapping error %d\n",err); return (1); }
vrep.clip_limit = view_map.proj_vp;
vrep.xy_clip = PIND_CLIP;
vrep.back_clip = PIND_CLIP;
vrep.front_clip = PIND_CLIP;
pset_view_rep3( thePHIGSWorkstation, viewNumber, &vrep);
bcopy( (char *)&vrep.ori_matrix, (char *)&theMatOri, sizeof(Pmatrix3));
bcopy( (char *)&vrep.map_matrix, (char *)&theMatMap, sizeof(Pmatrix3));
predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
return (0);
}
/*************************************************************************
* getNumberWidgetValue - get a number from a string widget.
*/
static int getNumberWidgetValue(int id, float *value)
{
double number;
char *text, *notText;
MrmCode class;
if (id > numberStringCount) return (1);
if (widgetArray[id] == NULL) { /* The first time, fetch order box. */
if (MrmFetchWidget(theMrmHierarchy, numberStrings[id], theTopLevel,
&widgetArray[id], &class) != MrmSUCCESS) {
printf("can't fetch number %d\n",id);
return (1);
}
}
/* View Reference Point */
XtVaGetValues(widgetArray[id], XmNvalue, &text, NULL);
number = strtod(text,¬Text);
if (number == 0.0 && text == notText) {
printf(" could get a number %s, %s\n",numberStrings[id],text);
return (1);
}
*value = (float) number;
return (0);
}
/*************************************************************************
* getWidgetValue - get a number from a string widget.
*/
static int getWidgetValue(int id, float *value)
{
double number;
char *text, *notText;
MrmCode class;
int intVal, i;
short decVal;
if (id > numberStringCount) return (1);
if (widgetArray[id] == NULL) { /* The first time, fetch order box. */
if (MrmFetchWidget(theMrmHierarchy, numberStrings[id], theTopLevel,
&widgetArray[id], &class) != MrmSUCCESS) {
printf("can't fetch number %d\n",id);
return (1);
}
}
/* View Reference Point */
XtVaGetValues(widgetArray[id],
XmNvalue, &intVal,
XmNdecimalPoints, &decVal,
NULL);
number = (double)intVal;
for (i = 0; i < (int)decVal; i++ ) number = number / 10.0;
/* printf ("getWidgetValue %d, %d, %d, %g\n", id, intVal, decVal, number); */
*value = (float) number;
return (0);
}
/*************************************************************************
* setNumberWidgetValue - set a number into a string widget.
*/
static int setNumberWidgetValue(int id, float value)
{
double number;
char text[80];
MrmCode class;
Arg al[1];
if (id > numberStringCount) return (1);
if (widgetArray[id] == NULL) { /* The first time, fetch order box. */
if (MrmFetchWidget(theMrmHierarchy, numberStrings[id], theTopLevel,
&widgetArray[id], &class) != MrmSUCCESS) {
printf("can't fetch number %d\n",id);
return (1);
}
}
sprintf(text, "%1.6f", value);
XtSetArg(al[0], XmNvalue, text );
XtSetValues(widgetArray[id], al, 1);
return (0);
}
/*************************************************************************
* DumpStrux
*
* In: strux - structure to dump
* element - is -1 do whole structure, else just that one
* pretty - use pretty formatting, dump into Motif window???
*/
void
DumpStrux( long strux, long element, int pretty )
{
int i;
Pint errind;
Pelem_data *data;
Pelem_type eType;
size_t eSize;
if (thePHIGSStore == (Pstore)0) {
pcreate_store(&i, &thePHIGSStore);
if ( i != 0 ) printf("trouble crating store %d\n", i);
}
if (element != -1) {
pinq_elem_type_size(strux,element,&errind,&eType,&eSize);
if (errind != 0) return;
pinq_elem_content(strux, element, thePHIGSStore, &errind, &data );
if (errind != 0) return;
PrintElement( strux, element, eType, (long)eSize, data );
} else {
errind = 0;
for (i = 1; errind == 0; i++ ) {
pinq_elem_type_size(strux,i,&errind,&eType,&eSize);
if (errind != 0) return;
pinq_elem_content(strux, i, thePHIGSStore, &errind, &data );
if (errind != 0) return;
PrintElement( strux, i, eType, (long)eSize, data );
}
}
}
/*************************************************************************
* PrintElement - dump out the element contents in hex.
*/
void
PrintElement( long struxID, long element, Pelem_type eType, long eSize,
Pelem_data *data )
{
long i, *p;
static char *mnemonics[] = {
"ALL", "NIL", "POLYLINE3", "POLYLINE", "POLYMARKER3",
"POLYMARKER", "TEXT3", "TEXT", "ANNO_TEXT_REL3", "ANNO_TEXT_REL",
"FILL_AREA3", "FILL_AREA", "FILL_AREA_SET3", "FILL_AREA_SET", "CELL_ARRAY3",
"CELL_ARRAY", "GDP3", "GDP", "LINE_IND", "MARKER_IND",
"TEXT_IND", "INT_IND", "EDGE_IND", "LINETYPE", "LINEWIDTH",
"LINE_COLR_IND", "MARKER_TYPE", "MARKER_SIZE", "MARKER_COLR_IND", "TEXT_FONT",
"TEXT_PREC", "CHAR_EXPAN", "CHAR_SPACE", "TEXT_COLR_IND", "CHAR_HT",
"CHAR_UP_VEC", "TEXT_PATH", "TEXT_ALIGN", "ANNO_CHAR_HT", "ANNO_CHAR_UP_VEC",
"ANNO_PATH", "ANNO_ALIGN", "ANNO_STYLE", "INT_STYLE", "INT_STYLE_IND",
"INT_COLR_IND", "EDGE_FLAG", "EDGETYPE", "EDGEWIDTH", "EDGE_COLR_IND",
"PAT_SIZE", "PAT_REF_POINT_VECS", "PAT_REF_POINT", "ADD_NAMES_SET",
"REMOVE_NAMES_SET",
"INDIV_ASF", "HLHSR_ID", "LOCAL_MODEL_TRAN3", "LOCAL_MODEL_TRAN",
"GLOBAL_MODEL_TRAN3",
"GLOBAL_MODEL_TRAN", "MODEL_CLIP_VOL3", "MODEL_CLIP_VOL", "MODEL_CLIP_IND",
"RESTORE_MODEL_CLIP_VOL",
"VIEW_IND", "EXEC_STRUCT", "LABEL", "APPL_DATA", "GSE",
"PICK_ID", "POLYLINE_SET3_DATA", "FILL_AREA_SET3_DATA", "TRI_STRIP3_DATA",
"QUAD_MESH3_DATA",
"SET_OF_FILL_AREA_SET3_DATA", "NUNI_BSP_CURVE", "NUNI_BSP_SURF",
"CELL_ARRAY3_PLUS", "TEXT_COLR",
"MARKER_COLR", "EDGE_COLR", "LINE_COLR", "CURVE_APPROX_CRIT", "LINE_SHAD_METH",
"INT_COLR", "BACK_INT_COLR", "BACK_INT_STYLE", "BACK_INT_STYLE_IND",
"REFL_PROPS",
"BACK_REFL_PROPS", "INT_SHAD_METH", "BACK_INT_SHAD_METH", "INT_REFL_EQN",
"BACK_INT_REFL_EQN",
"SURF_APPROX_CRIT", "PARA_SURF_CHARACS", "FACE_DISTING_MODE", "FACE_CULL_MODE",
"LIGHT_SRC_STATE", "DCUE_IND", "COLR_MAP_IND", "RENDERING_COLR_MODEL"
};
printf("\n strux %d, element %d, type_no %d, size = %d mnemonic = %s\n",
struxID, element, (int)eType, eSize, mnemonics[(int)eType] );
p = (long *)data;
if (eSize == 0) {
if (eType == PELEM_LOCAL_MODEL_TRAN3) {
for (i = 0; i < 16; i++, p++ ){
if ((i&0x7) == 7) printf("\n");
printf(" %x,", *p);
}}
} else {
for (i = 0; i < (eSize>>2); i++, p++ ){
if ((i&0x7) == 7) printf("\n");
printf(" %x,", *p);
}
}
}
/*************************************************************************
* ResizeWorkstation
*
* uses rubber sheet. The alternative would be porthole.
*
* It changes the Workstation Window (NPC) to the aspect ratio of the window.
* It changes the Workstation Viewport (DC) to the size of the window.
*
* To do porthole, the Workstation Window would move around NPC. The
* Workstation Viewport would still be the whole window.
*
* Watch out for X Window, View Window and Workstation Window confusion.
*/
void ResizeWorkstation(long wkid, int width, int height)
{
float d, minx, maxx, miny, maxy;
Plimit viewport;
Plimit3 window;
if (width > height) {
minx = 0.0; maxx = 1.0;
d = (float)(width-height)/(float)(2.0 * width);
miny = d; maxy = 1.0 - d;
}
else {
miny = 0.0; maxy = 1.0;
d = (float)(height-width)/(float)(2.0 * height);
minx = d; maxx = 1.0 - d;
}
viewport.x_min = 0.0;
viewport.x_max = (float)width;
viewport.y_min = 0.0;
viewport.y_max = (float)height;
pset_ws_vp( wkid, &viewport );
window.x_min = (Pfloat)minx;
window.x_max = (Pfloat)maxx;
window.y_min = (Pfloat)miny;
window.y_max = (Pfloat)maxy;
window.z_min = 0.0;
window.z_max = 1.0;
pset_ws_win3( wkid, &window );
}
/*************************************************************************
* InitLights - random init of two lights.
*/
InitLights(long wkid)
{
Plight_src_bundle Light;
/* Set the ambient light */
Light.type = PLIGHT_AMBIENT;
Light.rec.ambient.colr.type = PMODEL_RGB;
Light.rec.ambient.colr.val.general.x = 0.7; /* reddish gray */
Light.rec.ambient.colr.val.general.y = 0.3;
Light.rec.ambient.colr.val.general.z = 0.3;
pset_light_src_rep(wkid, 1, &Light);
/* Set the directional light */
Light.type = PLIGHT_DIRECTIONAL;
Light.rec.directional.colr.type = PMODEL_RGB;
Light.rec.directional.colr.val.general.x = 1.0; /* blue */
Light.rec.directional.colr.val.general.y = 1.0;
Light.rec.directional.colr.val.general.z = 1.0;
/*
* Note: the light source direction vector points from the light to the
* object - light should be in front, to the left, above
*/
Light.rec.directional.dir.delta_x = 1.0;
Light.rec.directional.dir.delta_y = -1.0;
Light.rec.directional.dir.delta_z = -1.0;
NormalizeVector(&Light.rec.directional.dir);
pset_light_src_rep(wkid, 2, &Light);
}
/*************************************************************************
* NormalizeVector
*/
int
NormalizeVector(v)
Pvec3 *v;
{
register float len;
#define SQR(x) ((x)*(x))
len = sqrt(SQR(v->delta_x) + SQR(v->delta_y) + SQR(v->delta_z));
if (len == 0.0)
return (0);
len = 1.0 / len; /* divides are expensive, do this to save 2 divides */
v->delta_x *= len;
v->delta_y *= len;
v->delta_z *= len;
return (1);
}
/*************************************************************************
* RotateObject - rather boring preemtive spinning of object. But it gets
* it reset back to identity.
*
*/
static void RotateObject(long wkid, long struxid, long count)
{
Ppoint3 pt;
Pvec3 shift;
Pvec3 scale;
Pfloat x_ang;
Pfloat y_ang;
Pfloat z_ang;
Pint degree,
err;
Pmatrix3 bldmat;
long step;
step = 360/count;
popen_struct(struxid);
pset_edit_mode(PEDIT_REPLACE);
pset_elem_ptr(MATRIX_ELEM);
pt.x = 0.0;
pt.y = 0.0;
pt.z = 0.0;
shift.delta_x = 0;
shift.delta_y = 0;
shift.delta_z = 0;
scale.delta_x = 1.0;
scale.delta_y = 1.0;
scale.delta_z = 1.0;
for (degree = 0; degree < 361; degree += step) {
x_ang = RADIAN(degree);
y_ang = 0;
z_ang = 0;
pbuild_tran_matrix3(&pt, &shift, x_ang, y_ang, z_ang, &scale, &err, bldmat);
pset_local_tran3(bldmat, PTYPE_REPLACE);
predraw_all_structs(wkid, PFLAG_ALWAYS);
}
for (degree = 0; degree < 361; degree += step) {
x_ang = 0;
y_ang = RADIAN(degree);
z_ang = 0;
pbuild_tran_matrix3(&pt, &shift, x_ang, y_ang, z_ang, &scale, &err, bldmat);
pset_local_tran3(bldmat, PTYPE_REPLACE);
predraw_all_structs(wkid, PFLAG_ALWAYS);
}
for (degree = 0; degree < 361; degree += step) {
x_ang = 0;
y_ang = 0;
z_ang = RADIAN(degree);
pbuild_tran_matrix3(&pt, &shift, x_ang, y_ang, z_ang, &scale, &err, bldmat);
pset_local_tran3(bldmat, PTYPE_REPLACE);
predraw_all_structs(wkid, PFLAG_ALWAYS);
}
/* reset it so we do not have to worry about translate on insert */
protate_x(0.0, &err, bldmat);
pset_local_tran3(bldmat, PTYPE_REPLACE); /* MATRIX_ELEM 7 */
pclose_struct();
pset_edit_mode(PEDIT_INSERT);
}
/*************************************************************************
* StartSpinning - install oneSpin as a Motif "work proc"
*
* set up the Global theSpinInfo to allow oneSpin to incrementally spin
* theNewStrux. This is installed as a Motif work proc and gets called
* whenever the XtMainLoop has nothing better to do.
*
* SEE ALSO, StopSpinning(). This sets theSpinInfo.stop which gets returned
* by oneSpin each time it is called. A non-zero value mean that the work
* proc is done.
*/
static void StartSpinning(long wkid, long struxid, long count)
{
theSpinInfo.point.x = 0.0;
theSpinInfo.point.y = 0.0;
theSpinInfo.point.z = 0.0;
theSpinInfo.offset.delta_x = 0;
theSpinInfo.offset.delta_y = 0;
theSpinInfo.offset.delta_z = 0;
theSpinInfo.scale.delta_x = 1.0;
theSpinInfo.scale.delta_y = 1.0;
theSpinInfo.scale.delta_z = 1.0;
theSpinInfo.x_ang = 0.0;
theSpinInfo.y_ang = 0.0;
theSpinInfo.z_ang = 0.0;
theSpinInfo.delta_x = (float)6/count;
theSpinInfo.delta_y = (float)4/count;
theSpinInfo.delta_z = 0.0;
theSpinInfo.strux_id = struxid;
theSpinInfo.wk_id = wkid;
theSpinInfo.dpy = XtDisplay(theDrawingArea);
theSpinInfo.stop = 0;
XtAppAddWorkProc(theAppContext,oneSpin,(XtPointer)&theSpinInfo);
}
/*************************************************************************
* oneSpin - Motif "work proc" for spinning a structure
*/
Boolean oneSpin(char *client_data)
{
SpinInfo *si;
Pint error;
Pmatrix3 matrix;
si = (SpinInfo *)client_data;
popen_struct(si->strux_id);
pset_edit_mode(PEDIT_REPLACE);
pset_elem_ptr(MATRIX_ELEM);
si->x_ang += si->delta_x;
si->y_ang += si->delta_y;
si->z_ang += si->delta_z;
pbuild_tran_matrix3(&si->point, &si->offset,
si->x_ang, si->y_ang, si->z_ang,
&si->scale, &error, matrix);
pset_local_tran3(matrix, PTYPE_REPLACE);
predraw_all_structs(si->wk_id, PFLAG_ALWAYS);
pclose_struct();
pset_edit_mode(PEDIT_INSERT);
XSync(si->dpy, 0);
return (si->stop);
}
static void StopSpinning(long wkid)
{
theSpinInfo.stop = 1;
}
/*************************************************************************
* CreateDynGC - create an X GC Resource for Dynamics.
*
* Got the rubberbanding methodology from contrib/clients/xfig/w_drawPrim.c
* But just the idea, no code was copied, hence no copyright.
*
* The idea is to xor ( exclusive or ) the foreground and the background
* together. When it is xor'd with the background it produces the foreground.
*/
static GC CreateDynGC(Widget drawArea)
{
XGCValues values;
unsigned long fg, bg;
GC tGC;
XtVaGetValues(drawArea, XmNforeground, &fg, XmNbackground, &bg, NULL);
values.foreground = fg ^ bg;
values.background = bg;
values.function = GXxor;
tGC = XCreateGC(XtDisplay(drawArea),XtWindow(drawArea),
GCFunction | GCForeground | GCBackground, &values );
return (tGC);
}
/*************************************************************************
* ReadArchiveFile
*
* Find all of the root structures - first find all structres and weed out
* those that are instanced by others.
* Read the whole archive, should do this be reading networks of posters, but..
* Post all of the poster candidates.
*/
static int ReadArchiveFile(char *filename)
{
Pint arid;
Pint_list ids;
Pint junk[10];
Pint posters[10], pCount;
Pint nIDs;
int i, j;
Pint status;
Pelem_ref_list_list *paths;
/*
* Set the conflict resolution to always overwrite everything. Open Archive.
*/
pset_conf_res(PRES_UPD, PRES_UPD);
thePHIGSError = 0;
popen_ar_file(arid, filename);
if (thePHIGSError) {
printf("Cannot open PHIGS Archive file %s\n", filename);
return (thePHIGSError);
}
ids.ints = (Pint *)junk;
pret_struct_ids(arid, 9, 0, &ids, &nIDs);
printf("read archive %s, ret_struct_ids total %d, count = %d, first = %d\n",
filename, nIDs, ids.num_ints, ids.ints[0] );
if (thePHIGSStore == (Pstore)0) {
pcreate_store(&i, &thePHIGSStore);
if ( i != 0 ) printf("trouble crating store %d\n", i);
}
pCount = 0;
for (i = 0; i < nIDs; i++ ) {
/* printf("ret_ances i = %d, id = %d\n", i, ids.ints[i]); */
pret_paths_ances(arid, ids.ints[i], PORDER_TOP_FIRST,
1, thePHIGSStore, &paths, &status);
if (status != 0) {
printf("imagine a motif alarm! return archive ancestors error %d\n",
status);
continue;
}
if (paths->num_elem_ref_lists != 0) continue; /* instanced in archive */
posters[pCount] = ids.ints[i]; pCount++;
}
pret_all_structs(arid);
pclose_ar_file(arid);
for (i = 0; i < pCount; i++ ) {
ppost_struct(thePHIGSWorkstation, posters[i], 1.0);
}
}
/*************************************************************************
* WriteArchiveFile
*/
static int WriteArchiveFile(char *filename)
{
Pint arid;
pset_conf_res(PRES_UPD, PRES_UPD);
popen_ar_file(arid, filename);
par_all_structs(arid);
pclose_ar_file(arid);
printf("closed archive file %s\n", filename);
}
/*************************************************************************
* DeleteAllStrux
*
* Currently, (a bug, I think), redraw_all_structs will not clear.
*/
static void DeleteAllStrux()
{
pdel_all_structs();
theNewStrux = 0;
predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
}
/*************************************************************************
* MyPHIGSErrorHandler - called by PHIGS when there is an error.
*
* This routine gets called instead of perr_hand() by the PHIGS library
* when an error occurs. It does exactly what perr_hand does except that
* it also sets the global, thePHIGSError. For sections of code that
* need to know if an error has occurred, set thePHIGSError to zero and
* make the calls, then check the global. See ReadArchiveFile().
*/
static void MyPHIGSErrorHandler( Pint errnum, Pint funcnum, char *fname)
{
thePHIGSError = errnum;
perr_log( errnum, funcnum, fname);
}
/*************************************************************************
*
*/
static void fbInitView( XButtonPressedEvent *event )
{
Pvec3 vpn;
float tsinTheta;
theDynX = event->x;
theDynY = event->y;
/* view plane normal */
getNumberWidgetValue(k_view_pl_norm_x, &vpn.delta_x);
getNumberWidgetValue(k_view_pl_norm_y, &vpn.delta_y);
getNumberWidgetValue(k_view_pl_norm_z, &vpn.delta_z);
NormalizeVector(&vpn); /* just in case the user was playing */
/*
* theta = atan2(cos(phi)*sin(theta), cos(phi)*cos(theta))
*/
theTheta = atan2(vpn.delta_x, vpn.delta_z);
/*
* atan2(sin(theta), cos(theta)) gives theta.
* since we have sin(phi) = dy and dx = cos(phi)*sin(theta)
* we want atan2(dy, dx/sin(theta)) BUT sin(theta) will be zero
* so we use dy*sin(theta) BUT when sin(theta) and dx are negative
* it changes the quadrant. so...
*/
tsinTheta = sin(theTheta);
if (tsinTheta >= 0 ) {
thePhi = atan2( vpn.delta_y * tsinTheta, vpn.delta_x);
} else {
thePhi = atan2( -(vpn.delta_y * tsinTheta), -vpn.delta_x);
}
thedebug = 1;
printf("start t %g, p %g, x,y,z %g, %g, %g\n", theTheta, thePhi,
vpn.delta_x, vpn.delta_y, vpn.delta_z);
}
static void fbDynView( XMotionEvent *event )
{
Pvec3 vpn;
Pvec3 vup;
float cx, cy, cz;
int t, c;
theTheta += 0.005 * (theDynX - event->x);
thePhi += 0.005 * (event->y - theDynY);
theDynX = event->x;
theDynY = event->y;
vpn.delta_x = cos( thePhi ) * sin( theTheta );
vpn.delta_y = sin( thePhi );
vpn.delta_z = cos( thePhi ) * cos( theTheta );
/* view up vector */
getNumberWidgetValue(k_view_up_vect_x, &vup.delta_x);
getNumberWidgetValue(k_view_up_vect_y, &vup.delta_y);
getNumberWidgetValue(k_view_up_vect_z, &vup.delta_z);
t = 6; c = 0;
while (t--) {
cx = vpn.delta_y*vup.delta_z - vpn.delta_z*vup.delta_y;
cy = vpn.delta_z*vup.delta_x - vpn.delta_x*vup.delta_z;
cz = vpn.delta_x*vup.delta_y - vpn.delta_y*vup.delta_x;
if ((cx*cx + cy*cy + cz*cz) < 0.1) {
if ((vup.delta_y < 0.8) && (vup.delta_y > -0.8)) {
vup.delta_y += 0.03;
} else {
vup.delta_x += 0.05;
}
NormalizeVector(&vup);
c = 1;
} else {
t = 0;
}
}
if (c) {
setNumberWidgetValue(k_view_up_vect_x, vup.delta_x);
setNumberWidgetValue(k_view_up_vect_y, vup.delta_y);
setNumberWidgetValue(k_view_up_vect_z, vup.delta_z);
}
setNumberWidgetValue(k_view_pl_norm_x, vpn.delta_x);
setNumberWidgetValue(k_view_pl_norm_y, vpn.delta_y);
setNumberWidgetValue(k_view_pl_norm_z, vpn.delta_z);
applyViewSet(1);
}
static void fbEndView( XButtonReleasedEvent *event )
{
Window root, child;
int root_x, root_y;
int win_x, win_y;
unsigned int keys_buttons;
XQueryPointer(XtDisplay(theDrawingArea),XtWindow(theDrawingArea),
&root, &child, &root_x, &root_y, &win_x, &win_y,
&keys_buttons);
XQueryPointer(XtDisplay(theDrawingArea),XtWindow(theDrawingArea),
&root, &child, &root_x, &root_y, &win_x, &win_y,
&keys_buttons);
if ((win_x != theDynX) && (win_y != theDynY)) {
printf("spinning... %d, %d, %d, %d\n",
theDynX,win_x,theDynY,win_y);
}
}
/*************************************************************************
* ApplySurfaceAttrs
*/
void
ApplySurfaceAttrs()
{
Pint error, ptr;
Pint errind;
Pelem_data *data;
Pelem_type eType;
size_t eSize;
Pint_style style;
Pint shade;
Pint cull;
float value;
#ifndef NO_TRANS
Pxrefl_props reflProps;
#else
Prefl_props reflProps;
#endif
MrmCode class;
if (theSurfaceForm == NULL) { /* The first time, fetch order box. */
if (MrmFetchWidget(theMrmHierarchy, "surface_dialog", theTopLevel,
&theSurfaceForm, &class) != MrmSUCCESS) {
printf("can't fetch Surface set dialog");
return;
}
}
if (theSelectedElement == -1) return;
popen_struct(theSelectedStrux);
if (XmToggleButtonGetState(widgetArray[k_sstyle_hollow]))
style = PSTYLE_HOLLOW;
else if (XmToggleButtonGetState(widgetArray[k_sstyle_solid]))
style = PSTYLE_SOLID;
else if (XmToggleButtonGetState(widgetArray[k_sstyle_empty]))
style = PSTYLE_EMPTY;
else {
printf("bad style\n");
style = PSTYLE_SOLID;
}
pset_elem_ptr(INT_STYLE_ELEM);
pdel_elem();
pset_int_style(style);
if (XmToggleButtonGetState(widgetArray[k_sshade_flat]))
shade = PSD_NONE;
else if (XmToggleButtonGetState(widgetArray[k_sshade_gouraud]))
shade = PSD_COLOUR;
else if (XmToggleButtonGetState(widgetArray[k_sshade_dot]))
shade = PSD_DOT_PRODUCT;
else if (XmToggleButtonGetState(widgetArray[k_sshade_phong]))
shade = PSD_NORMAL;
else {
printf("bad shade\n");
shade = PSD_COLOUR;
}
pset_elem_ptr(INT_SHAD_ELEM);
pdel_elem();
pset_int_shad_meth(shade);
if (XmToggleButtonGetState(widgetArray[k_cull_none]))
cull = PCULL_NONE;
else if (XmToggleButtonGetState(widgetArray[k_cull_back]))
cull = PCULL_BACKFACE;
else if (XmToggleButtonGetState(widgetArray[k_cull_front]))
cull = PCULL_FRONTFACE;
else {
printf("bad cull\n");
cull = PCULL_NONE;
}
if (thePHIGSStore == (Pstore)0) {
pcreate_store(&errind, &thePHIGSStore);
if ( errind != 0 ) printf("trouble crating store %d\n", errind);
goto end;
}
pset_elem_ptr(FACE_CULL_MODE);
pinq_cur_elem_type_size(&errind,&eType,&eSize);
if (errind != 0) goto end;
if (eType == PELEM_FACE_CULL_MODE) pdel_elem(); else {
poffset_elem_ptr(-1);
theSelectedElement++;
}
pset_face_cull_mode(cull);
#ifndef NO_TRANS
if (getWidgetValue(k_surface_refl_transparency, &value)) goto end;
if (value > /* arbitrary threshold for transparency */0.00001 ) {
reflProps.transpar_coef = value;
} else reflProps.transpar_coef = 0.0;
#endif
if (getWidgetValue(k_surface_refl_ambient, &value)) goto end;
reflProps.ambient_coef = value; /* ambient coefficient */
if (getWidgetValue(k_surface_refl_diffuse, &value)) goto end;
reflProps.diffuse_coef = value; /* diffuse coefficient */
if (getWidgetValue(k_surface_refl_specular, &value)) goto end;
reflProps.specular_coef = value; /* specular coefficient */
/* set specular color to white */
reflProps.specular_colr.type = PMODEL_RGB; /* specular color model */
reflProps.specular_colr.val.general.x = 1.0;
reflProps.specular_colr.val.general.y = 1.0;
reflProps.specular_colr.val.general.z = 1.0;
if (getWidgetValue(k_surface_refl_specexp, &value)) goto end;
reflProps.specular_exp = value; /* specular exponent */
pset_elem_ptr(REFL_PROPS_ELEM);
pdel_elem();
#ifndef NO_TRANS
pxset_refl_props(&reflProps);
#else
pset_refl_props(&reflProps);
#endif
end:
pclose_struct();
}
/*************************************************************************
* The following routine is taken from Tom Gaskin's example light_toy.c
* (would that the light form were there, too!)
* build_sphere only.
* It is copyright Tom Gaskins, O'Reilly & Associates, Inc. 1992.
* See the book, page xxxvi for further details.
*/
#define NUM_LONG_FACETS 32
#define NUM_LONG_POINTS (NUM_LONG_FACETS + 1)
#define NUM_LAT_FACETS 16
#define NUM_LAT_POINTS (NUM_LAT_FACETS + 1)
#define RADIUS 1.3
static void
build_sphere(long struxID)
{
Pptnorm3 vertex_data[NUM_LONG_POINTS * NUM_LAT_POINTS];
Pfacet_vdata_arr3 vertices;
Pint_size array_dims;
double theta = 0, phi = 0;
int i, j, index;
Ppoint_list3 plist;
Ppoint3 p[2];
for ( i = 0; i < NUM_LAT_POINTS; i++ ) {
for ( j = 0; j < NUM_LONG_FACETS; j++ ) {
index = i * NUM_LONG_POINTS + j;
vertex_data[index].norm.delta_x = - sin(phi) * cos(theta);
vertex_data[index].norm.delta_y = - cos(phi);
vertex_data[index].norm.delta_z = - sin(phi) * sin(theta);
vertex_data[index].point.x = RADIUS * 1+ vertex_data[index].norm.delta_x;
vertex_data[index].point.y = RADIUS * 1+ vertex_data[index].norm.delta_y;
vertex_data[index].point.z = RADIUS * 1+ vertex_data[index].norm.delta_z;
theta += (2 * M_PI) / NUM_LONG_FACETS;
}
phi += M_PI / NUM_LAT_FACETS;
/* Close the circle. */
index = i * NUM_LONG_POINTS + NUM_LONG_FACETS;
vertex_data[index].point = vertex_data[index - NUM_LONG_FACETS].point;
vertex_data[index].norm = vertex_data[index - NUM_LONG_FACETS].norm;
}
InitStrux(struxID);
popen_struct(struxID);
vertices.ptnorms = vertex_data;
array_dims.size_x = NUM_LONG_POINTS;
array_dims.size_y = NUM_LAT_POINTS;
pset_int_colr_ind(2);
pquad_mesh3_data( PFACET_NONE, PVERT_COORD_NORMAL, PMODEL_RGB,
&array_dims, (Pfacet_data_arr3 *)NULL, &vertices );
pset_line_colr_ind(4);
p[0].x = 0; p[0].y = 0; p[0].z = 0;
p[1].x = 1; p[1].y = 1; p[1].z = 1;
plist.points = p;
plist.num_points = 2;
ppolyline3( &plist );
pclose_struct();
}