This is example3.c in view mode; [Download] [Up]
/*
* example3.c: external module with bi-directional communication
*
* This example module is distributed with the geomview manual.
* If you are not reading this in the manual, see the "External
* Modules" chapter of the manual for an explanation.
*
* This module is the same as the "Nose" program that is distributed
* with geomview. It illustrates how a module can find out about
* and respond to user pick events in geomview. It draws a little box
* at the point where a pick occurrs. The box is yellow if it is not
* at a vertex, and magenta if it is on a vertex. If it is on an edge,
* the program also marks the edge.
*
* To compile:
*
* cc -I/u/gcg/ngrap/include -g -o example3 example3.c \
* -L/u/gcg/ngrap/lib/sgi -loogl -lm
*
* If you are not on the Geometry Center's system you should replace
* "/u/gcg/ngrap" above with the pathname of the geomview distribution
* directory on your system.
*/
#include <stdio.h>
#include "lisp.h" /* We use the OOGL lisp library */
#include "pickfunc.h" /* for PICKFUNC below */
#include "3d.h" /* for 3d geometry library */
/* boxstring gives the OOGL data to define the little box that
* we draw at the pick point. NOTE: It is very important to
* have a newline at the end of the OFF object in this string.
*/
char boxstring[] = "\
INST\n\
transform\n\
.04 0 0 0\n\
0 .04 0 0\n\
0 0 .04 0\n\
0 0 0 1\n\
geom\n\
OFF\n\
8 6 12\n\
\n\
-.5 -.5 -.5 # 0 \n\
.5 -.5 -.5 # 1 \n\
.5 .5 -.5 # 2 \n\
-.5 .5 -.5 # 3 \n\
-.5 -.5 .5 # 4 \n\
.5 -.5 .5 # 5 \n\
.5 .5 .5 # 6 \n\
-.5 .5 .5 # 7 \n\
\n\
4 0 1 2 3\n\
4 4 5 6 7\n\
4 2 3 7 6\n\
4 0 1 5 4\n\
4 0 4 7 3\n\
4 1 2 6 5\n";
progn()
{
printf("(progn\n");
}
endprogn()
{
printf(")\n");
fflush(stdout);
}
Initialize()
{
extern LObject *Lpick(); /* This is defined by PICKFUNC below but must */
/* be used in the following LDefun() call */
LInit();
LDefun("pick", Lpick, NULL);
progn(); {
/* Define handle "littlebox" for use later
*/
printf("(read geometry { define littlebox { %s }})\n", boxstring);
/* Express interest in pick events; see geomview manual for explanation.
*/
printf("(interest (pick world * * * * nil nil nil nil nil))\n");
/* Define "pick" object, initially the empty list (= null object).
* We replace this later upon receiving a pick event.
*/
printf("(geometry \"pick\" { LIST } )\n");
/* Make the "pick" object be non-pickable.
*/
printf("(pickable \"pick\" no)\n");
/* Turn off normalization, so that our pick object will appear in the
* right place.
*/
printf("(normalization \"pick\" none)\n");
/* Don't draw the pick object's bounding box.
*/
printf("(bbox-draw \"pick\" off)\n");
} endprogn();
}
/* The following is a macro call that defines a procedure called
* Lpick(). The reason for doing this in a macro is that that macro
* encapsulates a lot of necessary stuff that would be the same for
* this procedure in any program. If you write a geomview module that
* wants to know about user pick events you can just copy this macro
* call and change the body to suit your needs; the body is the last
* argument to the macro and is delimited by curly braces.
*
* The first argument to the macro is the name of the procedure to
* be defined, "Lpick".
*
* The next two arguments are numbers which specify the sizes that
* certain arrays inside the body of the procedure should have.
* These arrays are used for storing the face and path information
* of the picked object. In this module we don't care about this
* information so we declare them to have length 1, the minimum
* allowed.
*
* The last argument is a block of code to be executed when the module
* receives a pick event. In this body you can refer to certain local
* variables that hold information about the pick. For details see
* Example 3 in the Extenal Modules chapter of the geomview manual.
*/
PICKFUNC(Lpick, 1, 1,
{
handle_pick(pn>0, &point, vn>0, &vertex, en>0, edge);
})
handle_pick(picked, p, vert, v, edge, e)
int picked; /* was something actually picked? */
int vert; /* was the pick near a vertex? */
int edge; /* was the pick near an edge? */
HPoint3 *p; /* coords of pick point */
HPoint3 *v; /* coords of picked vertex */
HPoint3 e[2]; /* coords of endpoints of picked edge */
{
Normalize(&e[0]); /* Normalize makes 4th coord 1.0 */
Normalize(&e[1]);
Normalize(p);
progn(); {
if (!picked) {
printf("(geometry \"pick\" { LIST } )\n");
} else {
/*
* Put the box in place, and color it magenta if it's on a vertex,
* yellow if not.
*/
printf("(xform-set pick { 1 0 0 0 0 1 0 0 0 0 1 0 %g %g %g 1 })\n",
p->x, p->y, p->z);
printf("(geometry \"pick\"\n");
if (vert) printf("{ appearance { material { diffuse 1 0 1 } }\n");
else printf("{ appearance { material { diffuse 1 1 0 } }\n");
printf(" { LIST { :littlebox }\n");
/*
* If it's on an edge and not a vertex, mark the edge
* with cyan boxes at the endpoins and a yellow line
* along the edge.
*/
if (edge && !vert) {
e[0].x -= p->x; e[0].y -= p->y; e[0].z -= p->z;
e[1].x -= p->x; e[1].y -= p->y; e[1].z -= p->z;
printf("{ appearance { material { diffuse 0 1 1 } }\n\
LIST\n\
{ INST transform 1 0 0 0 0 1 0 0 0 0 1 0 %f %f %f 1 geom :littlebox }\n\
{ INST transform 1 0 0 0 0 1 0 0 0 0 1 0 %f %f %f 1 geom :littlebox }\n\
{ VECT\n\
1 2 1\n\
2\n\
1\n\
%f %f %f\n\
%f %f %f\n\
1 1 0 1\n\
}\n\
}\n",
e[0].x, e[0].y, e[0].z,
e[1].x, e[1].y, e[1].z,
e[0].x, e[0].y, e[0].z,
e[1].x, e[1].y, e[1].z);
}
printf(" }\n }\n)\n");
}
} endprogn();
}
Normalize(HPoint3 *p)
{
if (p->w != 0) {
p->x /= p->w;
p->y /= p->w;
p->z /= p->w;
p->w = 1;
}
}
main()
{
Lake *lake;
LObject *lit, *val;
extern char *getenv();
Initialize();
lake = LakeDefine(stdin, stdout, NULL);
while (!feof(stdin)) {
/* Parse next lisp expression from stdin.
*/
lit = LSexpr(lake);
/* Evaluate that expression; this is where Lpick() gets called.
*/
val = LEval(lit);
/* Free the two expressions from above.
*/
LFree(lit);
LFree(val);
}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.