home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Photo CD Demo 1
/
Demo.bin
/
icoons
/
source
/
spl_gfx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-20
|
43KB
|
1,422 lines
/* :ts=8 */
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "general.h"
#include "globals.h"
#include "intui.h"
#include "spl_math.h"
#include "spl_util.h"
#include "spl_gfx.h"
/* Constants and macros used by the clipping routine: */
#define OutCode_Top 0x01
#define OutCode_Bottom 0x02
#define OutCode_Right 0x04
#define OutCode_Left 0x08
/* Compute 'OutCode' for position (X,Y) and return it in C */
#define Compute_OutCode(X, Y, C) \
C = 0; \
if (Y > YMax) C = OutCode_Top; \
else if (Y < YMin) C = OutCode_Bottom; \
if (X > XMax) C |= OutCode_Right; \
else if (X < XMin) C |= OutCode_Left
/* Clip and draw line (X0,Y0) - (X1,Y1) in view V. */
#define ViewClipDrawLine(V, X0, Y0, X1, Y1) \
ClipDrawLine(X0, Y0, X1, Y1, \
Views[V].X_Min, Views[V].X_Max, \
Views[V].Y_Min, Views[V].Y_Max)
void ClipDrawLine(short X0, short Y0, short X1, short Y1,
short XMin, short XMax, short YMin, short YMax)
/************************************************************************/
/* */
/* Clip and draw the line from (X0, Y0) - (X1, Y1) to the rectangle */
/* given by (XMin, YMin) - (XMax, YMax). */
/* */
/* This is the Cohen-Sutherland algorithm as described in */
/* Computer graphics p. 113 - 117. */
/* */
/************************************************************************/
{
Boolean_T Accept, Done;
long OutCode0, OutCode1, OutCodeOut;
int X, Y;
Accept = Done = FALSE;
Compute_OutCode(X0, Y0, OutCode0);
Compute_OutCode(X1, Y1, OutCode1);
do {
if (OutCode0 == 0 && OutCode1 == 0) Accept = Done = TRUE;
else if ((OutCode0 & OutCode1) != 0) Done = TRUE;
else {
/* Failed both tests, so calculate the line segment to */
/* clip: from an outside point to an intersection with */
/* clip edge. */
/* At least one endpoint is outside the clip rectangle, */
/* pick it. */
if (OutCode0 != 0) OutCodeOut = OutCode0;
else OutCodeOut = OutCode1;
/* Now find intersection point: */
if (OutCodeOut & OutCode_Top) {
/* Divide line at top of clip rectangle */
if (Y0 == Y1) Done = TRUE;
else {
X = X0 + (X1 - X0) * (YMax - Y0) / (Y1 - Y0);
Y = YMax;
}
} else if (OutCodeOut & OutCode_Bottom) {
/* Divide line at bottom of clip rectangle */
if (Y0 == Y1) Done = TRUE;
else {
X = X0 + (X1 - X0) * (YMin - Y0) / (Y1 - Y0);
Y = YMin;
}
} else if (OutCodeOut & OutCode_Right) {
/* Divide line at right of clip rectangle */
if (X0 == X1) Done = TRUE;
else {
X = XMax;
Y = Y0 + (Y1 - Y0) * (XMax - X0) / (X1 - X0);
}
} else if (OutCodeOut & OutCode_Left) {
/* Divide line at left of clip rectangle */
if (X0 == X1) Done = TRUE;
else {
X = XMin;
Y = Y0 + (Y1 - Y0) * (XMin - X0) / (X1 - X0);
}
} /* if .. else .. */
/* Now we move outside point to intersection point to clip, */
/* and get ready for next pass. */
if (OutCodeOut == OutCode0) {
X0 = X;
Y0 = Y;
Compute_OutCode(X0, Y0, OutCode0);
} else {
X1 = X;
Y1 = Y;
Compute_OutCode(X1, Y1, OutCode1);
} /* if .. else .. */
} /* if .. else .. */
} while (!Done);
if (Accept) {
/* Draw from (X0, Y0) to (X1, Y1) */
Move(Windows[Id_Active_Window].RastPort, X0, Y0);
Draw(Windows[Id_Active_Window].RastPort, X1, Y1);
} /* if */
} /* ClipDrawLine */
void Modify_Scale(double Factor)
/************************************************************************/
/* */
/* Modify the scale factor. */
/* */
/************************************************************************/
{
X_Scale_Factor *= Factor;
Y_Scale_Factor *= Factor;
Max_Dist = 5.0 / Y_Scale_Factor;
} /* Modify_Scale */
void Transformation_Init()
/************************************************************************/
/* */
/* Initialize all transformation parameters. */
/* */
/************************************************************************/
{
Vector_T Initial_Offset = { 0.0, 0.0, 0.0 };
Y_Scale_Factor = 0.5;
X_Scale_Factor = Aspect_Ratio * Y_Scale_Factor;
Modify_Scale(1.0);
Compute_Rotation_Matrix(M_Rotation, Rotation_Vector);
Set_Offset(Initial_Offset, -1);
} /* Transformation_Init */
void Set_Offset(Vector_T Pos, short View_Id)
/************************************************************************/
/* */
/* Set the offset to Pos. View_Id designates the view in which the */
/* offset is changed (-1 => all views). */
/* */
/************************************************************************/
{
switch (View_Id) {
case -1: /* All views */
Offset[0] = Pos[0];
Offset[1] = Pos[1];
Offset[2] = Pos[2];
break;
case 0: /* Y - Z */
Offset[1] = Pos[1];
Offset[2] = Pos[2];
break;
case 1: /* X - Z */
Offset[0] = Pos[0];
Offset[2] = Pos[2];
break;
case 2: /* X - Y */
Offset[0] = Pos[0];
Offset[1] = Pos[1];
break;
} /* switch */
} /* Set_Offset */
void Move_Offset(short Direction, short View_Id)
/************************************************************************/
/* */
/* Move offset in the view given by View_Id in the direction given by */
/* Direction (0: Up, 1: Down, 2: Right, 3: Left). */
/* */
/* The distance moved depends on the current scale factor. */
/* */
/************************************************************************/
{
double Delta;
Vector_T New_Offset;
Vec2Op(New_Offset, =, Offset);
Delta = 100.0 / Y_Scale_Factor;
switch (Direction) {
case 0: /* Up */
switch (View_Id) {
case 0: New_Offset[2] = Offset[2] + Delta; break;
case 1: New_Offset[2] = Offset[2] + Delta; break;
case 2: New_Offset[1] = Offset[1] + Delta; break;
} /* switch */
break;
case 1: /* Down */
switch (View_Id) {
case 0: New_Offset[2] = Offset[2] - Delta; break;
case 1: New_Offset[2] = Offset[2] - Delta; break;
case 2: New_Offset[1] = Offset[1] - Delta; break;
} /* switch */
break;
case 2: /* Right */
switch (View_Id) {
case 0: New_Offset[1] = Offset[1] + Delta; break;
case 1: New_Offset[0] = Offset[0] + Delta; break;
case 2: New_Offset[0] = Offset[0] + Delta; break;
} /* switch */
break;
case 3: /* Left */
switch (View_Id) {
case 0: New_Offset[1] = Offset[1] - Delta; break;
case 1: New_Offset[0] = Offset[0] - Delta; break;
case 2: New_Offset[0] = Offset[0] - Delta; break;
} /* switch */
break;
} /* Switch */
Set_Offset(New_Offset, -1);
} /* Move_Offset */
void Snap_To_Grid(Vector_T Pos)
/************************************************************************/
/* */
/* Snap the point Pos to the grid. */
/* */
/************************************************************************/
{
double Size2;
Size2 = Grid_Size / 2.0;
Pos[0] = SGN(Pos[0]) * Grid_Size * ( (int)((ABS(Pos[0]) + Size2) / Grid_Size));
Pos[1] = SGN(Pos[1]) * Grid_Size * ( (int)((ABS(Pos[1]) + Size2) / Grid_Size));
Pos[2] = SGN(Pos[2]) * Grid_Size * ( (int)((ABS(Pos[2]) + Size2) / Grid_Size));
} /* Snap_To_Grid */
short Screen_To_World(int Screen_X, int Screen_Y, Vector_T Pos)
/************************************************************************/
/* */
/* Convert the screen coordinates (Screen_X, Screen_Y) to a world coor- */
/* dinate, and return id of the view where (Screen_X, Screen_Y) is. */
/* */
/* NOTICE: This function can only find two of the three world coordi- */
/* nates. The third will not be modified by this routine. */
/* */
/************************************************************************/
{
if ((What_Mask & What_X) &&
Screen_X >= Views[V_X].X_Min &&
Screen_X <= Views[V_X].X_Max &&
Screen_Y >= Views[V_X].Y_Min &&
Screen_Y <= Views[V_X].Y_Max) { /* View X: Y-Z */
Pos[1] = (Screen_X - Views[V_X].X_Center) / X_Scale_Factor +
Offset[1];
Pos[2] = (Views[V_X].Y_Center - Screen_Y) / Y_Scale_Factor +
Offset[2];
return(V_X);
} /* if */
if ((What_Mask & What_Y) &&
Screen_X >= Views[V_Y].X_Min &&
Screen_X <= Views[V_Y].X_Max &&
Screen_Y >= Views[V_Y].Y_Min &&
Screen_Y <= Views[V_Y].Y_Max) { /* View Y: X-Z */
Pos[0] = (Screen_X - Views[V_Y].X_Center) / X_Scale_Factor +
Offset[0];
Pos[2] = (Views[V_Y].Y_Center - Screen_Y) / Y_Scale_Factor +
Offset[2];
return(V_Y);
} /* if */
if ((What_Mask & What_Z) &&
Screen_X >= Views[V_Z].X_Min &&
Screen_X <= Views[V_Z].X_Max &&
Screen_Y >= Views[V_Z].Y_Min &&
Screen_Y <= Views[V_Z].Y_Max) { /* View Z: X-Y */
Pos[0] = (Screen_X - Views[V_Z].X_Center) / X_Scale_Factor +
Offset[0];
Pos[1] = (Views[V_Z].Y_Center - Screen_Y) / Y_Scale_Factor +
Offset[1];
return(V_Z);
} /* if */
if ((What_Mask & What_P) &&
Screen_X >= Views[V_P].X_Min &&
Screen_X <= Views[V_P].X_Max &&
Screen_Y >= Views[V_P].Y_Min &&
Screen_Y <= Views[V_P].Y_Max) { /* View P: Persp*/
/* Points can't be selected in persp view (yet) */
return(-1);
} /* if */
return(-1);
} /* Screen_To_World */
void World_To_Screen(Vector_T Pos, short *X0, short *Y0,
short *X1, short *Y1,
short *X2, short *Y2)
/************************************************************************/
/* */
/* Convert the world coordinate in Pos to screen coordinates for the */
/* three 'flat' views. */
/* */
/* This function is called all the time, so it is a good place for opti-*/
/* mization. */
/* */
/************************************************************************/
{
Vector_T P;
Vec3Op(P, =, Pos, -, Offset);
*X0 = Views[V_X].X_Center + P[1] * X_Scale_Factor; /* X : Y - Z */
*Y0 = Views[V_X].Y_Center - P[2] * Y_Scale_Factor;
*X1 = Views[V_Y].X_Center + P[0] * X_Scale_Factor; /* Y : X - Z */
*Y1 = Views[V_Y].Y_Center - P[2] * Y_Scale_Factor;
*X2 = Views[V_Z].X_Center + P[0] * X_Scale_Factor; /* Z : X - Y */
*Y2 = Views[V_Z].Y_Center - P[1] * Y_Scale_Factor;
} /* World_To_Screen */
void World_To_Persp(Vector_T Pos, short *X, short *Y)
/************************************************************************/
/* */
/* Convert the world coordinate in Pos to screen coordinates for the */
/* perspective view. */
/* */
/* This function is called all the time, so it is a good place for opti-*/
/* mization. */
/* */
/************************************************************************/
{
Vector_T P, RP;
Vec3Op(P, =, Pos, -, Offset);
Matrix_MultV(RP, M_Rotation, P);
*X = Views[V_P].X_Center + RP[0] * X_Scale_Factor;
*Y = Views[V_P].Y_Center - RP[2] * Y_Scale_Factor;
} /* World_To_Persp */
void Unmark_All()
/************************************************************************/
/* */
/* Unmark all splines, knots and points. */
/* */
/************************************************************************/
{
short i;
short Point_Id;
Spline_T *Spline;
Knot_T *Knot;
for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
if (Spline->Nbr_Knots > 0) {
Do_Unmark(*Spline);
for (i = 0, Knot = Spline->First;
i < Spline->Nbr_Knots; i++, Knot = Knot->Next)
Do_Unmark(*Knot);
} /* if */
} /* for */
for (Point_Id = 0; Point_Id < Max_Nbr_Points; Point_Id++)
Do_Unmark(Points[Point_Id]);
} /* Unmark_All */
void Mark_Selected_Segments()
/************************************************************************/
/* */
/* Mark the currently selected segments. */
/* */
/************************************************************************/
{
Knot_T *Knot, *Begin_Knot, *End_Knot;
Unmark_All();
if (Select_Spline == NULL || Select_Knot == NULL) return;
if (Select_Spline->Nbr_Knots < 2) return;
if (Select_Spline->Nbr_Knots < 5) {
Begin_Knot = Select_Spline->First;
if (Select_Spline->Loop)
End_Knot = Select_Spline->Last->Next;
else End_Knot = Select_Spline->Last;
} else {
Begin_Knot = Select_Knot;
if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;
if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;
End_Knot = Select_Knot;
if (End_Knot->Next) End_Knot = End_Knot->Next;
End_Knot = End_Knot->Next;
} /* if .. else .. */
/* Loop from Begin_Knot to End_Knot (exclusive) */
Knot = Begin_Knot;
do {
Do_Mark(*Knot);
Knot = Knot->Next;
} while (Knot != End_Knot);
} /* Mark_Selected_Segments */
void Mark_Connected_Segments(short Point_Id)
/************************************************************************/
/* */
/* Mark segments connected to point Point_Id. */
/* */
/************************************************************************/
{
Spline_T *Spline;
Knot_T *K, *Knot, *Begin_Knot, *End_Knot;
short i;
if (!Is_Point_Id_Ok(Point_Id)) return;
Unmark_All();
for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
if (Spline->Nbr_Knots < 2) continue;
Knot = NULL;
for (i = 0, K = Spline->First; i < Spline->Nbr_Knots;
i++, K = K->Next)
if (K->Point_Id == Point_Id) Knot = K;
if (Knot == NULL) continue;
if (Spline->Nbr_Knots < 5) {
Begin_Knot = Spline->First;
if (Spline->Loop) End_Knot = Spline->Last->Next;
else End_Knot = Spline->Last;
} else {
Begin_Knot = Knot;
if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;
if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;
End_Knot = Knot;
if (End_Knot->Next) End_Knot = End_Knot->Next;
End_Knot = End_Knot->Next;
} /* if .. else .. */
/* Loop from Begin_Knot to End_Knot (exclusive) */
Knot = Begin_Knot;
do {
Do_Mark(*Knot);
Knot = Knot->Next;
} while (Knot != End_Knot);
} /* for */
} /* Mark_Connected_Segments */
void Compute_Segment(Spline_T *Spline, Knot_T *Knot)
/************************************************************************/
/* */
/* Compute a spline segment. */
/* */
/* This function is using a brute force iterative evaluation, it would */
/* be much better to use a forward difference method as described in */
/* Computer Graphics p. 511 - 514. */
/* Oh well, maybe another time... */
/* */
/************************************************************************/
{
Matrix4_T M_Precomp;
Vector4_T Pos;
double Step_T;
double T;
Byte_T NX, NY, NZ, NP;
NX = NY = NZ = NP = 0;
if (Spline->Nbr_Knots < 2) return;
Step_T = 1.0 / Spline_Resolution;
Precompute_Kochanek_Bartels(M_Precomp, Spline, Knot);
for (T = 0.0; T <= 1.0; T += Step_T) {
Compute_Position(Pos, T, M_Precomp);
World_To_Screen(Pos,&Knot->ViewX[NX][0], &Knot->ViewX[NX][1],
&Knot->ViewY[NY][0], &Knot->ViewY[NY][1],
&Knot->ViewZ[NZ][0], &Knot->ViewZ[NZ][1]);
World_To_Persp(Pos, &Knot->ViewP[NP][0], &Knot->ViewP[NP][1]);
/* Simple clipping: The line must be entirely within the*/
/* views. */
if (Views[V_X].X_Min < Knot->ViewX[NX][0] &&
Views[V_X].Y_Min < Knot->ViewX[NX][1] &&
Views[V_X].X_Max > Knot->ViewX[NX][0] &&
Views[V_X].Y_Max > Knot->ViewX[NX][1]) NX++;
if (Views[V_Y].X_Min < Knot->ViewY[NY][0] &&
Views[V_Y].Y_Min < Knot->ViewY[NY][1] &&
Views[V_Y].X_Max > Knot->ViewY[NY][0] &&
Views[V_Y].Y_Max > Knot->ViewY[NY][1]) NY++;
if (Views[V_Z].X_Min < Knot->ViewZ[NZ][0] &&
Views[V_Z].Y_Min < Knot->ViewZ[NZ][1] &&
Views[V_Z].X_Max > Knot->ViewZ[NZ][0] &&
Views[V_Z].Y_Max > Knot->ViewZ[NZ][1]) NZ++;
if (Views[V_P].X_Min < Knot->ViewP[NP][0] &&
Views[V_P].Y_Min < Knot->ViewP[NP][1] &&
Views[V_P].X_Max > Knot->ViewP[NP][0] &&
Views[V_P].Y_Max > Knot->ViewP[NP][1]) NP++;
} /* for */
Knot->NX = NX;
Knot->NY = NY;
Knot->NZ = NZ;
Knot->NP = NP;
} /* Compute_Segment */
void Compute_Marked_Segments()
/************************************************************************/
/* */
/* Compute vectors for all marked segments. */
/* */
/************************************************************************/
{
int i;
Spline_T *Spline;
Knot_T *Knot;
int Nbr_Knots;
for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
if ((Nbr_Knots = Spline->Nbr_Knots) < 1) continue;
for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots;
i++, Knot = Knot->Next) {
if (Is_Marked(*Spline) || Is_Marked(*Knot) ) {
Compute_Segment(Spline, Knot);
} /* if */
} /* for */
} /* for */
} /* Compute_Marked_Segments */
void Compute_Spline(Spline_T *Spline)
/************************************************************************/
/* */
/* Compute vectors for a given spline. */
/* */
/************************************************************************/
{
Knot_T *Knot;
int i;
int Nbr_Knots;
if ((Nbr_Knots = Spline->Nbr_Knots) < 1) return;
for (i = 0, Knot = Spline->First; i < Nbr_Knots; i++, Knot = Knot->Next) {
if (!Is_Hidden(Points[Knot->Point_Id]))
Compute_Segment(Spline, Knot);
} /* for */
} /* Compute_Spline */
void Compute_Splines()
/************************************************************************/
/* */
/* Compute vectors for all splines. */
/* */
/************************************************************************/
{
Spline_T *Spline;
Set_Pointer(TRUE);
for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
Compute_Spline(Spline);
} /* for */
Set_Pointer(FALSE);
} /* Compute_Splines */
void Draw_Segment(Spline_T *Spline, Knot_T *Knot, int Pen, long What)
/************************************************************************/
/* */
/* Draw a spline segment. */
/* */
/* The segment must have been 'computed' before calling this function. */
/* */
/************************************************************************/
{
Knot_T *Next_Knot;
What &= What_Mask;
/* If either of the endpoints is hidden, */
/* then don't draw the segment */
Next_Knot = Knot->Next;
if (Next_Knot == NULL) return;
if (Is_Hidden(Points[Next_Knot->Point_Id]) ||
Is_Hidden(Points[Knot->Point_Id]) ) return;
SetAPen(Windows[Id_Active_Window].RastPort, Pen);
if ( (What & What_SX) && (Knot->NX > 1) ) {
Move(Windows[Id_Active_Window].RastPort, Knot->ViewX[0][0],
Knot->ViewX[0][1]);
PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NX-1,
&Knot->ViewX[1][0]);
} /* if */
if ( (What & What_SY) && (Knot->NY > 1) ) {
Move(Windows[Id_Active_Window].RastPort, Knot->ViewY[0][0],
Knot->ViewY[0][1]);
PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NY-1,
&Knot->ViewY[1][0]);
} /* if */
if ( (What & What_SZ) && (Knot->NZ > 1) ) {
Move(Windows[Id_Active_Window].RastPort, Knot->ViewZ[0][0],
Knot->ViewZ[0][1]);
PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NZ-1,
&Knot->ViewZ[1][0]);
} /* if */
if ( (What & What_SP) && (Knot->NP > 1) ) {
Move(Windows[Id_Active_Window].RastPort, Knot->ViewP[0][0],
Knot->ViewP[0][1]);
PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NP-1,
&Knot->ViewP[1][0]);
} /* if */
} /* Draw_Segment */
void Draw_Marked_Segments(Draw_Mode_T Mode, long What)
/************************************************************************/
/* */
/* Draw all marked segments. */
/* */
/************************************************************************/
{
Spline_T *Spline;
Knot_T *Knot;
int i;
short Nbr_Knots;
int Pen;
switch (Mode) {
case DM_Normal: /* Normal draw */
Pen = Pen_Segment;
Windows[Id_Active_Window].RastPort->Mask = 0xff;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
break;
case DM_Erase: /* Delete */
Pen = Pen_Background;
Windows[Id_Active_Window].RastPort->Mask = 0xff;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
break;
case DM_Plane: /* Draw in plane 3 */
Pen = Pen_Plane;
Windows[Id_Active_Window].RastPort->Mask = 0x08;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
break;
} /* switch */
for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
if ((Nbr_Knots = Spline->Nbr_Knots) < 2) continue;
for (i = 0, Knot = Spline->First;
i < Nbr_Knots && Knot->Next != NULL; i++, Knot = Knot->Next) {
if (Is_Marked(*Spline) || Is_Marked(*Knot) ) {
if (Mode == DM_Normal) {
Pen = Pen_Segment;
if (Select_Spline == Spline) {
if (Select_Knot == Knot ||
Select_Knot == Knot->Next) Pen = Pen_Segment_Selected;
} /* if */
} /* if */
Draw_Segment(Spline, Knot, Pen, What);
Draw_Knot(Spline, Knot, Mode, What);
} /* if */
} /* for */
} /* for */
Draw_Knot(Select_Spline, Select_Knot, Mode, What);
} /* Draw_Marked_Segments */
void Draw_Spline(Spline_T *Spline , Draw_Mode_T Mode, long What)
/************************************************************************/
/* */
/* Draw a spline. */
/* */
/************************************************************************/
{
Knot_T *Knot;
int i;
short Nbr_Knots;
int Pen;
if (Spline == NULL) return;
if ((Nbr_Knots = Spline->Nbr_Knots) < 1) return;
switch (Mode) {
case DM_Normal: /* Normal draw */
Pen = Pen_Segment;
Windows[Id_Active_Window].RastPort->Mask = 0xff;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
break;
case DM_Erase: /* Delete */
Pen = Pen_Background;
Windows[Id_Active_Window].RastPort->Mask = 0xff;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
break;
case DM_Plane: /* Draw in plane 3 */
Pen = Pen_Plane;
Windows[Id_Active_Window].RastPort->Mask = 0x08;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
break;
} /* switch */
for (i = 0, Knot = Spline->First;
i < Nbr_Knots && Knot->Next != NULL; i++, Knot = Knot->Next) {
if (Mode == DM_Normal) {
Pen = Pen_Segment;
if (Select_Spline == Spline) {
if (Select_Knot == Knot ||
Select_Knot == Knot->Next) Pen = Pen_Segment_Selected;
} /* if */
} /* if */
Draw_Segment(Spline, Knot, Pen, What);
Draw_Knot(Spline, Knot, Mode, What);
} /* for */
Draw_Knot(Spline, Knot, Mode, What);
} /* Draw_Spline */
void Draw_Splines(Draw_Mode_T Mode, long What)
/************************************************************************/
/* */
/* Draw all splines. */
/* */
/************************************************************************/
{
Spline_T *Spline;
for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
Draw_Spline(Spline, Mode, What);
} /* for */
} /* Draw_Splines */
void Draw_Origin(Draw_Mode_T Mode, long What)
/************************************************************************/
/* */
/* Draw the origin. */
/* */
/************************************************************************/
{
short Xx0, Yx0, Xy0, Yy0, Xz0, Yz0, Xp0, Yp0;
short Xx1, Yx1, Xy1, Yy1, Xz1, Yz1, Xp1, Yp1;
Vector_T Vector;
double Size;
int Pen;
What &= What_Mask;
switch (Mode) {
case DM_Normal:
Pen = Pen_Segment;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
Windows[Id_Active_Window].RastPort->Mask = 0xff;
break;
case DM_Erase:
Pen = Pen_Background;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM2);
Windows[Id_Active_Window].RastPort->Mask = 0xff;
break;
case DM_Plane:
Pen = Pen_Plane;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
Windows[Id_Active_Window].RastPort->Mask = 0x08;
break;
} /* switch */
World_To_Screen(Origin, &Xx0, &Yx0, &Xy0, &Yy0, &Xz0, &Yz0);
World_To_Persp(Origin, &Xp0, &Yp0);
Size = 10.0 / Y_Scale_Factor;
/* X - Axis */
Vector[0] = Origin[0] + Size;
Vector[1] = Origin[1];
Vector[2] = Origin[2];
World_To_Screen(Vector, &Xx1, &Yx1, &Xy1, &Yy1, &Xz1, &Yz1);
World_To_Persp(Vector, &Xp1, &Yp1);
if (Mode == DM_Normal) Pen = Pen_Axis_X;
SetAPen(Windows[Id_Active_Window].RastPort, Pen);
if (What & What_X) ViewClipDrawLine(V_X, Xx0, Yx0, Xx1, Yx1);
if (What & What_Y) ViewClipDrawLine(V_Y, Xy0, Yy0, Xy1, Yy1);
if (What & What_Z) ViewClipDrawLine(V_Z, Xz0, Yz0, Xz1, Yz1);
if (What & What_P) ViewClipDrawLine(V_P, Xp0, Yp0, Xp1, Yp1);
/* Y - Axis */
Vector[0] = Origin[0];
Vector[1] = Origin[1] + Size;
Vector[2] = Origin[2];
World_To_Screen(Vector, &Xx1, &Yx1, &Xy1, &Yy1, &Xz1, &Yz1);
World_To_Persp(Vector, &Xp1, &Yp1);
if (Mode == DM_Normal) Pen = Pen_Axis_Y;
SetAPen(Windows[Id_Active_Window].RastPort, Pen);
if (What & What_X) ViewClipDrawLine(V_X, Xx0, Yx0, Xx1, Yx1);
if (What & What_Y) ViewClipDrawLine(V_Y, Xy0, Yy0, Xy1, Yy1);
if (What & What_Z) ViewClipDrawLine(V_Z, Xz0, Yz0, Xz1, Yz1);
if (What & What_P) ViewClipDrawLine(V_P, Xp0, Yp0, Xp1, Yp1);
/* Z - Axis */
Vector[0] = Origin[0];
Vector[1] = Origin[1];
Vector[2] = Origin[2] + Size;
World_To_Screen(Vector, &Xx1, &Yx1, &Xy1, &Yy1, &Xz1, &Yz1);
World_To_Persp(Vector, &Xp1, &Yp1);
if (Mode == DM_Normal) Pen = Pen_Axis_Z;
SetAPen(Windows[Id_Active_Window].RastPort, Pen);
if (What & What_X) ViewClipDrawLine(V_X, Xx0, Yx0, Xx1, Yx1);
if (What & What_Y) ViewClipDrawLine(V_Y, Xy0, Yy0, Xy1, Yy1);
if (What & What_Z) ViewClipDrawLine(V_Z, Xz0, Yz0, Xz1, Yz1);
if (What & What_P) ViewClipDrawLine(V_P, Xp0, Yp0, Xp1, Yp1);
} /* Draw_Origin */
void Draw_Grid(long What)
/************************************************************************/
/* */
/* Draw the grid if it is active. */
/* */
/************************************************************************/
{
Vector_T Grid;
short X0x, Y0x, X0y, Y0y, X0z, Y0z;
short X1x, Y1x, X1y, Y1y, X1z, Y1z;
short X, Y;
int Dx, Dy;
long i;
if (!Grid_Active) return;
Vec2Op(Grid, =, Offset);
Snap_To_Grid(Grid);
World_To_Screen(Grid, &X0x, &Y0x, &X0y, &Y0y, &X0z, &Y0z);
Grid[0] = Offset[0] + Grid_Size;
Grid[1] = Offset[1] + Grid_Size;
Grid[2] = Offset[2] + Grid_Size;
Snap_To_Grid(Grid);
World_To_Screen(Grid, &X1x, &Y1x, &X1y, &Y1y, &X1z, &Y1z);
Dx = ABS(X1x - X0x); /* Size of grid in screen coordinates */
Dy = ABS(Y1x - Y0x);
if (Dx < 5 || Dx > 100 || Dy < 5 || Dy > 100) return;
i = (X0x - Views[V_X].X_Min) / Dx; X0x -= (i * Dx);
i = (Y0x - Views[V_X].Y_Min) / Dy; Y0x -= (i * Dy);
i = (X0y - Views[V_Y].X_Min) / Dx; X0y -= (i * Dx);
i = (Y0y - Views[V_Y].Y_Min) / Dy; Y0y -= (i * Dy);
i = (X0z - Views[V_Z].X_Min) / Dx; X0z -= (i * Dx);
i = (Y0z - Views[V_Z].Y_Min) / Dy; Y0z -= (i * Dy);
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
Windows[Id_Active_Window].RastPort->Mask = 0xff;
SetAPen(Windows[Id_Active_Window].RastPort, Pen_Grid);
What &= What_Mask;
if (What & What_X) {
for (X = X0x; X < Views[V_X].X_Max; X += Dx) {
for (Y = Y0x; Y < Views[V_X].Y_Max; Y += Dy) {
WritePixel(Windows[Id_Active_Window].RastPort, X, Y);
}
}
} /* if */
if (What & What_Y) {
for (X = X0y; X < Views[V_Y].X_Max; X += Dx) {
for (Y = Y0y; Y < Views[V_Y].Y_Max; Y += Dy) {
WritePixel(Windows[Id_Active_Window].RastPort, X, Y);
}
}
} /* if */
if (What & What_Z) {
for (X = X0z; X < Views[V_Z].X_Max; X += Dx) {
for (Y = Y0z; Y < Views[V_Z].Y_Max; Y += Dy) {
WritePixel(Windows[Id_Active_Window].RastPort, X, Y);
}
}
} /* if */
} /* Draw_Grid */
void Draw_Box(Vector_T Min_Pos, Vector_T Max_Pos, Vector_T R_Vector,
Draw_Mode_T Mode, long What)
/************************************************************************/
/* */
/* Draw a box after it has been rotated as defined by R_Vector. */
/* If R_Vector == NULL no rotation is performed. */
/* */
/************************************************************************/
{
Matrix_T R_Matrix;
Vector_T Tmp;
Vector_T Corners[8];
short X[8][4], Y[8][4];
int Pen;
int i;
What &= What_Mask;
switch (Mode) {
case DM_Normal:
Pen = Pen_Segment;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
Windows[Id_Active_Window].RastPort->Mask = 0xff;
break;
case DM_Erase:
Pen = Pen_Background;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM2);
Windows[Id_Active_Window].RastPort->Mask = 0xff;
break;
case DM_Plane:
Pen = Pen_Plane;
Windows[Id_Active_Window].RastPort->Mask = 0x08;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
break;
} /* switch */
SetAPen(Windows[Id_Active_Window].RastPort, Pen);
/* The eight corners: */
Vec3Scalar(Corners[0], = , Min_Pos[0], Min_Pos[1], Min_Pos[2]);
Vec3Scalar(Corners[1], = , Max_Pos[0], Min_Pos[1], Min_Pos[2]);
Vec3Scalar(Corners[2], = , Min_Pos[0], Max_Pos[1], Min_Pos[2]);
Vec3Scalar(Corners[3], = , Max_Pos[0], Max_Pos[1], Min_Pos[2]);
Vec3Scalar(Corners[4], = , Min_Pos[0], Min_Pos[1], Max_Pos[2]);
Vec3Scalar(Corners[5], = , Max_Pos[0], Min_Pos[1], Max_Pos[2]);
Vec3Scalar(Corners[6], = , Min_Pos[0], Max_Pos[1], Max_Pos[2]);
Vec3Scalar(Corners[7], = , Max_Pos[0], Max_Pos[1], Max_Pos[2]);
if (R_Vector != NULL) {
Compute_Rotation_Matrix(R_Matrix, R_Vector);
for (i = 0; i < 8; i++) {
Vec3Op(Corners[i], =, Corners[i], -, Origin);
Matrix_MultV(Tmp, R_Matrix, Corners[i]);
Vec3Op(Corners[i], =, Tmp, +, Origin);
} /* for */
} /* if */
if (What & What_K3)
for (i = 0; i < 8; i++)
World_To_Screen(Corners[i], &X[i][0], &Y[i][0],
&X[i][1], &Y[i][1],
&X[i][2], &Y[i][2]);
if (What & What_KP)
for (i = 0; i < 8; i++)
World_To_Persp(Corners[i], &X[i][3], &Y[i][3]);
if (What & What_KX) {
ViewClipDrawLine(V_X, X[0][0], Y[0][0], X[1][0], Y[1][0]);
ViewClipDrawLine(V_X, X[1][0], Y[1][0], X[3][0], Y[3][0]);
ViewClipDrawLine(V_X, X[3][0], Y[3][0], X[2][0], Y[2][0]);
ViewClipDrawLine(V_X, X[2][0], Y[2][0], X[0][0], Y[0][0]);
ViewClipDrawLine(V_X, X[4][0], Y[4][0], X[5][0], Y[5][0]);
ViewClipDrawLine(V_X, X[5][0], Y[5][0], X[7][0], Y[7][0]);
ViewClipDrawLine(V_X, X[7][0], Y[7][0], X[6][0], Y[6][0]);
ViewClipDrawLine(V_X, X[6][0], Y[6][0], X[4][0], Y[4][0]);
ViewClipDrawLine(V_X, X[0][0], Y[0][0], X[4][0], Y[4][0]);
ViewClipDrawLine(V_X, X[1][0], Y[1][0], X[5][0], Y[5][0]);
ViewClipDrawLine(V_X, X[2][0], Y[2][0], X[6][0], Y[6][0]);
ViewClipDrawLine(V_X, X[3][0], Y[3][0], X[7][0], Y[7][0]);
} /* if */
if (What & What_KY) {
ViewClipDrawLine(V_Y, X[0][1], Y[0][1], X[1][1], Y[1][1]);
ViewClipDrawLine(V_Y, X[1][1], Y[1][1], X[3][1], Y[3][1]);
ViewClipDrawLine(V_Y, X[3][1], Y[3][1], X[2][1], Y[2][1]);
ViewClipDrawLine(V_Y, X[2][1], Y[2][1], X[0][1], Y[0][1]);
ViewClipDrawLine(V_Y, X[4][1], Y[4][1], X[5][1], Y[5][1]);
ViewClipDrawLine(V_Y, X[5][1], Y[5][1], X[7][1], Y[7][1]);
ViewClipDrawLine(V_Y, X[7][1], Y[7][1], X[6][1], Y[6][1]);
ViewClipDrawLine(V_Y, X[6][1], Y[6][1], X[4][1], Y[4][1]);
ViewClipDrawLine(V_Y, X[0][1], Y[0][1], X[4][1], Y[4][1]);
ViewClipDrawLine(V_Y, X[1][1], Y[1][1], X[5][1], Y[5][1]);
ViewClipDrawLine(V_Y, X[2][1], Y[2][1], X[6][1], Y[6][1]);
ViewClipDrawLine(V_Y, X[3][1], Y[3][1], X[7][1], Y[7][1]);
} /* if */
if (What & What_KZ) {
ViewClipDrawLine(V_Z, X[0][2], Y[0][2], X[1][2], Y[1][2]);
ViewClipDrawLine(V_Z, X[1][2], Y[1][2], X[3][2], Y[3][2]);
ViewClipDrawLine(V_Z, X[3][2], Y[3][2], X[2][2], Y[2][2]);
ViewClipDrawLine(V_Z, X[2][2], Y[2][2], X[0][2], Y[0][2]);
ViewClipDrawLine(V_Z, X[4][2], Y[4][2], X[5][2], Y[5][2]);
ViewClipDrawLine(V_Z, X[5][2], Y[5][2], X[7][2], Y[7][2]);
ViewClipDrawLine(V_Z, X[7][2], Y[7][2], X[6][2], Y[6][2]);
ViewClipDrawLine(V_Z, X[6][2], Y[6][2], X[4][2], Y[4][2]);
ViewClipDrawLine(V_Z, X[0][2], Y[0][2], X[4][2], Y[4][2]);
ViewClipDrawLine(V_Z, X[1][2], Y[1][2], X[5][2], Y[5][2]);
ViewClipDrawLine(V_Z, X[2][2], Y[2][2], X[6][2], Y[6][2]);
ViewClipDrawLine(V_Z, X[3][2], Y[3][2], X[7][2], Y[7][2]);
} /* if */
if (What & What_KP) {
ViewClipDrawLine(V_P, X[0][3], Y[0][3], X[1][3], Y[1][3]);
ViewClipDrawLine(V_P, X[1][3], Y[1][3], X[3][3], Y[3][3]);
ViewClipDrawLine(V_P, X[3][3], Y[3][3], X[2][3], Y[2][3]);
ViewClipDrawLine(V_P, X[2][3], Y[2][3], X[0][3], Y[0][3]);
ViewClipDrawLine(V_P, X[4][3], Y[4][3], X[5][3], Y[5][3]);
ViewClipDrawLine(V_P, X[5][3], Y[5][3], X[7][3], Y[7][3]);
ViewClipDrawLine(V_P, X[7][3], Y[7][3], X[6][3], Y[6][3]);
ViewClipDrawLine(V_P, X[6][3], Y[6][3], X[4][3], Y[4][3]);
ViewClipDrawLine(V_P, X[0][3], Y[0][3], X[4][3], Y[4][3]);
ViewClipDrawLine(V_P, X[1][3], Y[1][3], X[5][3], Y[5][3]);
ViewClipDrawLine(V_P, X[2][3], Y[2][3], X[6][3], Y[6][3]);
ViewClipDrawLine(V_P, X[3][3], Y[3][3], X[7][3], Y[7][3]);
} /* if */
} /* Draw_Box */
void Draw_Knot(Spline_T *Spline, Knot_T *Knot, Draw_Mode_T Mode, long What)
/************************************************************************/
/* */
/* Draw a knot. */
/* Don't drow it in DM_Plane mode. */
/* */
/************************************************************************/
{
short Xx, Yx, Xy, Yy, Xz, Yz, Xp, Yp;
int Point_Id;
int Pen;
What &= What_Mask;
if (Spline == NULL || Knot == NULL) return;
Point_Id = Knot->Point_Id;
if (Is_Hidden(Points[Point_Id])) return;
switch (Mode) {
case DM_Normal:
if (Point_Id == Select_Point_Id) Pen = Pen_Knot_Primary;
else if (Is_Selected(Points[Point_Id])) Pen = Pen_Knot_Selected;
else Pen = Pen_Knot;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
Windows[Id_Active_Window].RastPort->Mask = 0xff;
break;
case DM_Erase:
Pen = Pen_Background;
SetDrMd(Windows[Id_Active_Window].RastPort, JAM2);
Windows[Id_Active_Window].RastPort->Mask = 0xff;
break;
case DM_Plane:
return;
} /* switch */
SetAPen(Windows[Id_Active_Window].RastPort, Pen);
if (What & What_K3)
World_To_Screen(Points[Point_Id].Pos, &Xx, &Yx, &Xy, &Yy, &Xz, &Yz);
if (What & What_KP)
World_To_Persp(Points[Point_Id].Pos, &Xp, &Yp);
#define DRAW_DOT
#ifdef DRAW_DOT
/* Draw knots as dots */
if (What & What_KX) {
/* Clipping */
if (Views[V_X].X_Min < Xx && Views[V_X].Y_Min < Yx &&
Views[V_X].X_Max > Xx && Views[V_X].Y_Max > Yx) {
WritePixel(Windows[Id_Active_Window].RastPort, Xx, Yx);
} /* if */
} /* if */
if (What & What_KY) {
if (Views[V_Y].X_Min < Xy && Views[V_Y].Y_Min < Yy &&
Views[V_Y].X_Max > Xy && Views[V_Y].Y_Max > Yy) {
WritePixel(Windows[Id_Active_Window].RastPort, Xy, Yy);
} /* if */
} /* if */
if (What & What_KZ) {
if (Views[V_Z].X_Min < Xz && Views[V_Z].Y_Min < Yz &&
Views[V_Z].X_Max > Xz && Views[V_Z].Y_Max > Yz) {
WritePixel(Windows[Id_Active_Window].RastPort, Xz, Yz);
} /* if */
} /* if */
if (What & What_KP) {
if (Views[V_P].X_Min < Xp && Views[V_P].Y_Min < Yp &&
Views[V_P].X_Max > Xp && Views[V_P].Y_Max > Yp) {
WritePixel(Windows[Id_Active_Window].RastPort, Xp, Yp);
} /* if */
} /* if */
#else
/* Draw knots as small crosses */
if (What & What_KX) {
/* Clipping */
if (Views[V_X].X_Min < Xx - 2 && Views[V_X].Y_Min < Yx - 2 &&
Views[V_X].X_Max > Xx + 2 && Views[V_X].Y_Max > Yx + 2) {
Move(Windows[Id_Active_Window].RastPort, Xx - 2, Yx);
Draw(Windows[Id_Active_Window].RastPort, Xx + 2, Yx);
Move(Windows[Id_Active_Window].RastPort, Xx , Yx - 2);
Draw(Windows[Id_Active_Window].RastPort, Xx , Yx + 2);
} /* if */
} /* if */
if (What & What_KY) {
if (Views[V_Y].X_Min < Xy - 2 && Views[V_Y].Y_Min < Yy - 2 &&
Views[V_Y].X_Max > Xy + 2 && Views[V_Y].Y_Max > Yy + 2) {
Move(Windows[Id_Active_Window].RastPort, Xy - 2, Yy);
Draw(Windows[Id_Active_Window].RastPort, Xy + 2, Yy);
Move(Windows[Id_Active_Window].RastPort, Xy , Yy - 2);
Draw(Windows[Id_Active_Window].RastPort, Xy , Yy + 2);
} /* if */
} /* if */
if (What & What_KZ) {
if (Views[V_Z].X_Min < Xz - 2 && Views[V_Z].Y_Min < Yz - 2 &&
Views[V_Z].X_Max > Xz + 2 && Views[V_Z].Y_Max > Yz + 2) {
Move(Windows[Id_Active_Window].RastPort, Xz - 2, Yz);
Draw(Windows[Id_Active_Window].RastPort, Xz + 2, Yz);
Move(Windows[Id_Active_Window].RastPort, Xz , Yz - 2);
Draw(Windows[Id_Active_Window].RastPort, Xz , Yz + 2);
} /* if */
} /* if */
if (What & What_KP) {
if (Views[V_P].X_Min < Xp - 2 && Views[V_P].Y_Min < Yp - 2 &&
Views[V_P].X_Max > Xp + 2 && Views[V_P].Y_Max > Yp + 2) {
Move(Windows[Id_Active_Window].RastPort, Xp - 2, Yp);
Draw(Windows[Id_Active_Window].RastPort, Xp + 2, Yp);
Move(Windows[Id_Active_Window].RastPort, Xp , Yp - 2);
Draw(Windows[Id_Active_Window].RastPort, Xp , Yp + 2);
} /* if */
} /* if */
#endif
} /* Draw_Knot */
void Draw_Knots(Draw_Mode_T Mode, long What)
/************************************************************************/
/* */
/* Draw all knots. */
/* */
/************************************************************************/
{
int i;
Spline_T *Spline;
Knot_T *Knot;
What &= What_Mask;
if ( (What & What_K) == 0) return;
for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
if (Spline->Nbr_Knots < 1) continue;
for (i = 0, Knot = Spline->First;
i < Spline->Nbr_Knots; i++, Knot = Knot->Next)
Draw_Knot(Spline, Knot, Mode, What);
} /* for */
} /* Draw_Knots */
void Draw_All(long What)
/************************************************************************/
/* */
/* Draw all splines, knots, grid and the origin. */
/* */
/************************************************************************/
{
Set_Pointer(TRUE);
Draw_Grid(What);
Draw_Splines(DM_Normal, What);
Draw_Origin(DM_Normal, What);
Set_Pointer(FALSE);
} /* Draw_All */