/***************************************************************************** * "Irit" - the 3d polygonal solid modeller. * * * * Written by: Gershon Elber Ver 0.1, Jan. 1992 * ****************************************************************************** * (C) Gershon Elber, Technion, Israel Institute of Technology * ****************************************************************************** * Main definition Header file for Irit - the 3d polygonal solid modeller. * *****************************************************************************/ #ifndef IRIT_SM_H #define IRIT_SM_H /* Note program version should also be updated in *.c modules, in few */ /* places, as some system can not chain strings in the pre-processor level. */ #define IRIT_VERSION "Version 9.5" /* Program version. */ #define IRIT_COPYRIGHT "(C) Copyright 1989-2005 Gershon Elber" #include #include #include #ifndef NULL #define NULL 0 #endif /* NULL */ #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif /* TRUE */ #ifdef VoidPtr #undef VoidPtr #endif /* VoidPtr */ #ifdef NO_VOID_PTR #define VoidPtr char * #else #define VoidPtr void * #endif /* NO_VOID_PTR */ #if !defined(IRIT_FLOAT) && !defined(IRIT_DOUBLE) #if defined(__MSDOS__) || defined(MAKE_REAL_IRIT_FLOAT) #define IRIT_FLOAT typedef float RealType; /* On IBMPC to reserve memory... */ #define REAL_TYPE_SIZE 0x04 #else #define IRIT_DOUBLE typedef double RealType; #define REAL_TYPE_SIZE 0x08 #endif /* __MSDOS__ || MAKE_REAL_IRIT_FLOAT */ #endif /* !IRIT_FLOAT && !IRIT_DOUBLE */ #ifdef DEBUG_IRIT_MALLOC #define DEBUG_IP_MALLOC #define DEBUG_ATTR_MALLOC #endif /* DEBUG_IRIT_MALLOC */ #ifdef DEBUG #define IRIT_SET_DEBUG_PARAMETER(DbgPrm, Val) \ STATIC_DATA int DbgPrm = Val #define IRIT_IF_DEBUG_ON_PARAMETER(DbgPrm) \ if (DbgPrm) #define IRIT_SET_IF_DEBUG_ON_PARAMETER(DbgPrm, Val) \ STATIC_DATA int DbgPrm = Val; \ if (DbgPrm) #endif /* DEBUG */ typedef unsigned char ByteType; typedef RealType PointType[3]; /* For X, Y, Z coordinates of point. */ typedef RealType VectorType[3]; /* For X, Y, Z coordinates of vector. */ typedef RealType LineType[3]; /* A, B, C in Ax + By + C = 0. */ typedef RealType NormalType[3]; /* Unit normalized normal coeff. */ typedef RealType PlaneType[4]; /* Plane equation coeff. */ typedef RealType MatrixType[4][4]; /* Homogeneous transform. */ typedef PointType BBoxType[2]; /* Axis parallel bounding box. */ /* The following is an integer that equal in size toa pointer in the system. */ #if defined(LINUX386) typedef long IritIntPtrSizeType; #else typedef int IritIntPtrSizeType; #endif /* LINUX386 */ #define IRIT_EPS 1e-5 #define IRIT_LARGE 1e5 #define IRIT_INFNTY 2.3197171528332553e+25 #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /* M_PI */ #define M_PI_DIV_2 1.57079632679489661923 #define M_PI_MUL_2 6.28318530717958647692 #ifndef M_SQRT2 #define M_SQRT2 1.41421356237309504880 #endif /* M_SQRT2 */ #define LINE_LEN_VLONG 1024 /* Lines read from stdin/files... */ #define LINE_LEN_LONG 256 /* Lines read from stdin/files... */ #define LINE_LEN 81 /* Lines read from stdin/files... */ #define LINE_LEN_SHORT 31 /* Lines read from stdin/files... */ #define OBJ_NAME_LEN 31 /* Names of objects. */ #define PATH_NAME_LEN 80 /* Name with full Path */ /* Follows by general purpose helpfull macros: */ #ifndef MIN #define MIN(x, y) ((x) > (y) ? (y) : (x)) #endif /* MIN */ #ifndef MAX #define MAX(x, y) ((x) > (y) ? (x) : (y)) #endif /* MAX */ #define BOUND(x, Min, Max) (MAX(MIN((x), Max), Min)) #define ABS(x) ((x) > 0 ? (x) : (-(x))) #define FABS(x) fabs(x) #define SQR(x) ((x) * (x)) #define CUBE(x) ((x) * (x) * (x)) #define SIGN(x) ((x) > 0 ? 1 : ((x) < 0 ? -1 : 0)) #define SWAP(type, x, y) { type temp = (x); x = (y); y = temp; } #define REAL_TO_INT(R) ((int) ((R) > 0.0 ? (R) + 0.5 : (R) - 0.5)) #define REAL_PTR_TO_INT(R) REAL_TO_INT(*(R)) #define GEN_COPY(Dest, Src, Size) memcpy((char *) (Dest), (char *) (Src), Size) #define GEN_CMP(Dest, Src, Size) memcmp((char *) (Dest), (char *) (Src), Size) #define ZAP_MEM(Dest, Size) memset((char *) (Dest), 0, Size); #ifdef IRIT_QUIET_STRINGS # define IRIT_EXP_STR(Str) "" # define IRIT_FATAL_ERROR(Str) IritFatalError("") # define IRIT_WARNING_MSG(Str) # define _IRIT_PT_NORMALIZE_MSG_ZERO(Size) #else # define IRIT_EXP_STR(Str) Str # define IRIT_FATAL_ERROR(Str) IritFatalError(Str) # define IRIT_WARNING_MSG(Str) IritWarningError(Str) # define _IRIT_PT_NORMALIZE_MSG_ZERO(Size) \ if (Size < PT_NORMALIZE_ZERO) { \ IritWarningError("Attempt to normalize a zero length vector\n"); \ } \ else #endif /* IRIT_QUIET_STRINGS */ #define CAGD_LARGE_BEZIER_CACHE #define APX_EQ(x, y) (FABS((x) - (y)) < IRIT_EPS) #define APX_EQ_EPS(x, y, EPS) (FABS((x) - (y)) < EPS) #define PT_APX_EQ(Pt1, Pt2) (APX_EQ((Pt1)[0], (Pt2)[0]) && \ APX_EQ((Pt1)[1], (Pt2)[1]) && \ APX_EQ((Pt1)[2], (Pt2)[2])) #define PT_APX_EQ_E2(Pt1, Pt2) (APX_EQ((Pt1)[0], (Pt2)[0]) && \ APX_EQ((Pt1)[1], (Pt2)[1])) #define PT_APX_EQ_EPS(Pt1, Pt2, EPS) \ (APX_EQ_EPS((Pt1)[0], (Pt2)[0], EPS) && \ APX_EQ_EPS((Pt1)[1], (Pt2)[1], EPS) && \ APX_EQ_EPS((Pt1)[2], (Pt2)[2], EPS)) #define PT_APX_EQ_E2_EPS(Pt1, Pt2, EPS) \ (APX_EQ_EPS((Pt1)[0], (Pt2)[0], EPS) && \ APX_EQ_EPS((Pt1)[1], (Pt2)[1], EPS)) #define PLANE_APX_EQ(Pl1, Pl2) (APX_EQ((Pl1)[0], (Pl2)[0]) && \ APX_EQ((Pl1)[1], (Pl2)[1]) && \ APX_EQ((Pl1)[2], (Pl2)[2]) && \ APX_EQ((Pl1)[3], (Pl2)[3])) #define PLANE_APX_EQ_EPS(Pl1, Pl2, EPS) (APX_EQ_EPS((Pl1)[0], (Pl2)[0], EPS) && \ APX_EQ_EPS((Pl1)[1], (Pl2)[1], EPS) && \ APX_EQ_EPS((Pl1)[2], (Pl2)[2], EPS) && \ APX_EQ_EPS((Pl1)[3], (Pl2)[3], EPS)) #define PT_APX_EQ_ZERO_EPS(Pt, EPS) \ (FABS((Pt)[0]) < EPS && \ FABS((Pt)[1]) < EPS && \ FABS((Pt)[2]) < EPS) #define PT_EQ_ZERO(Pt) ((Pt)[0] == 0.0 && (Pt)[1] == 0.0 && (Pt)[2] == 0.0) #ifdef IRIT_DOUBLE #define IRIT_UEPS 1e-14 #else #define IRIT_UEPS 1e-6 #endif /* IRIT_DOUBLE */ #define IRIT_APX_EQ(x, y) (FABS((x) - (y)) < IRIT_UEPS) #define IRIT_PT_APX_EQ(Pt1, Pt2) (IRIT_APX_EQ((Pt1)[0], (Pt2)[0]) && \ IRIT_APX_EQ((Pt1)[1], (Pt2)[1]) && \ IRIT_APX_EQ((Pt1)[2], (Pt2)[2])) #define PT_SCALE(Pt, Scalar) { (Pt)[0] *= Scalar; \ (Pt)[1] *= Scalar; \ (Pt)[2] *= Scalar; \ } #define PLANE_SCALE(Pl, Scalar) { (Pl)[0] *= Scalar; \ (Pl)[1] *= Scalar; \ (Pl)[2] *= Scalar; \ (Pl)[3] *= Scalar; \ } #define PT_SCALE2(Res, Pt, Scalar) \ { (Res)[0] = (Pt)[0] * Scalar; \ (Res)[1] = (Pt)[1] * Scalar; \ (Res)[2] = (Pt)[2] * Scalar; \ } /* The memcpy is sometimes defined to get (char *) pointers and sometimes */ /* (void *) pointers. To be compatible with both it is coerced to (char *). */ #define PT_COPY(PtDest, PtSrc) memcpy((char *) (PtDest), (char *) (PtSrc), \ 3 * sizeof(RealType)) #define PLANE_COPY(PlDest, PlSrc) memcpy((char *) (PlDest), (char *) (PlSrc), \ 4 * sizeof(RealType)) #define MAT_COPY(Dest, Src) memcpy((char *) (Dest), (char *) (Src), \ 16 * sizeof(RealType)) #define PT_SQR_LENGTH(Pt) (SQR((Pt)[0]) + SQR((Pt)[1]) + SQR((Pt)[2])) #define PT_LENGTH(Pt) sqrt(PT_SQR_LENGTH(Pt)) #define PT_RESET(Pt) ZAP_MEM((Pt), 3 * sizeof(RealType)) #define PLANE_RESET(Pl) ZAP_MEM((Pl), 4 * sizeof(RealType)) #define PT_NORMALIZE_ZERO 1e-30 #define PT_NORMALIZE(Pt) { \ RealType Size = PT_LENGTH((Pt)); \ _IRIT_PT_NORMALIZE_MSG_ZERO(Size) \ { \ Size = 1.0 / Size; \ PT_SCALE(Pt, Size); \ } \ } #define PT_SAFE_NORMALIZE(Pt) { \ RealType Size = PT_LENGTH((Pt)); \ if (Size > PT_NORMALIZE_ZERO) { \ Size = 1.0 / Size; \ PT_SCALE(Pt, Size); \ } \ } #define PT_CLEAN_NORMALIZE(Pt) { \ if (FABS(Pt[0]) < IRIT_UEPS) Pt[0] = 0; \ if (FABS(Pt[1]) < IRIT_UEPS) Pt[1] = 0; \ if (FABS(Pt[2]) < IRIT_UEPS) Pt[2] = 0; \ } #define PT_NORMALIZE_FLOAT(Pt) { \ float Size = (float) PT_LENGTH((Pt)); \ _IRIT_PT_NORMALIZE_MSG_ZERO(Size) \ { \ Size = 1.0F / Size; \ PT_SCALE(Pt, Size); \ } \ } #define PT_SET(Pt, Pt1, Pt2, Pt3) \ { (Pt)[0] = (Pt1); \ (Pt)[1] = (Pt2); \ (Pt)[2] = (Pt3); \ } #define PT_SCALE_AND_ADD(Res, Pt1, Pt2, t) \ { (Res)[0] = (Pt1)[0] + (Pt2)[0] * t; \ (Res)[1] = (Pt1)[1] + (Pt2)[1] * t; \ (Res)[2] = (Pt1)[2] + (Pt2)[2] * t; \ } #define PT_BLEND(Res, Pt1, Pt2, t) \ { (Res)[0] = (Pt1)[0] * t + (Pt2)[0] * (1 - t); \ (Res)[1] = (Pt1)[1] * t + (Pt2)[1] * (1 - t); \ (Res)[2] = (Pt1)[2] * t + (Pt2)[2] * (1 - t); \ } #define PT_BLEND_BARYCENTRIC(Res, Pt1, Pt2, Pt3, W) { \ Res[0] = Pt1[0] * W[0] + Pt2[0] * W[1] + Pt3[0] * W[2]; \ Res[1] = Pt1[1] * W[0] + Pt2[1] * W[1] + Pt3[1] * W[2]; \ Res[2] = Pt1[2] * W[0] + Pt2[2] * W[1] + Pt3[2] * W[2]; } \ #define PT_ADD(Res, Pt1, Pt2) { (Res)[0] = (Pt1)[0] + (Pt2)[0]; \ (Res)[1] = (Pt1)[1] + (Pt2)[1]; \ (Res)[2] = (Pt1)[2] + (Pt2)[2]; \ } #define PT_SUB(Res, Pt1, Pt2) { (Res)[0] = (Pt1)[0] - (Pt2)[0]; \ (Res)[1] = (Pt1)[1] - (Pt2)[1]; \ (Res)[2] = (Pt1)[2] - (Pt2)[2]; \ } #define PT_SWAP(Pt1, Pt2) { SWAP(RealType, (Pt1)[0], (Pt2)[0]); \ SWAP(RealType, (Pt1)[1], (Pt2)[1]); \ SWAP(RealType, (Pt1)[2], (Pt2)[2]); \ } #define PT_PT_DIST(Pt1, Pt2) sqrt(SQR((Pt1)[0] - (Pt2)[0]) + \ SQR((Pt1)[1] - (Pt2)[1]) + \ SQR((Pt1)[2] - (Pt2)[2])) #define PT_PT_DIST_SQR(Pt1, Pt2) (SQR((Pt1)[0] - (Pt2)[0]) + \ SQR((Pt1)[1] - (Pt2)[1]) + \ SQR((Pt1)[2] - (Pt2)[2])) /* Now the same thing but for 2D points. */ #define PT2D_SCALE(Pt, Scalar) { (Pt)[0] *= Scalar; \ (Pt)[1] *= Scalar; \ } #define PT2D_COPY(PtDest, PtSrc) memcpy((char *) (PtDest), (char *) (PtSrc), \ 2 * sizeof(RealType)) #define PT2D_SQR_LENGTH(Pt) (SQR((Pt)[0]) + SQR((Pt)[1])) #define PT2D_LENGTH(Pt) sqrt(PT2D_SQR_LENGTH(Pt)) #define PT2D_RESET(Pt) ZAP_MEM((Pt), 2 * sizeof(RealType)) #define PT2D_NORMALIZE(Pt) { \ RealType Size = PT2D_LENGTH((Pt)); \ _IRIT_PT_NORMALIZE_MSG_ZERO(Size) \ { \ Size = 1.0 / Size; \ PT2D_SCALE(Pt, Size); \ } \ } #define PT2D_SAFE_NORMALIZE(Pt) { \ RealType Size = PT2D_LENGTH((Pt)); \ if (Size > PT_NORMALIZE_ZERO) { \ Size = 1.0 / Size; \ PT2D_SCALE(Pt, Size); \ } \ } #define PT2D_NORMALIZE_FLOAT(Pt) { \ float Size = (float) PT2D_LENGTH((Pt)); \ _IRIT_PT_NORMALIZE_MSG_ZERO(Size) \ { \ Size = 1.0F / Size; \ PT2D_SCALE(Pt, Size); \ } \ } #define PT2D_SET(Pt, Pt1, Pt2, Pt3) \ { (Pt)[0] = (Pt1); \ (Pt)[1] = (Pt2); \ } #define PT2D_BLEND(Res, Pt1, Pt2, t) \ { (Res)[0] = (Pt1)[0] * t + (Pt2)[0] * (1 - t); \ (Res)[1] = (Pt1)[1] * t + (Pt2)[1] * (1 - t); \ } #define PT2D_ADD(Res, Pt1, Pt2) { (Res)[0] = (Pt1)[0] + (Pt2)[0]; \ (Res)[1] = (Pt1)[1] + (Pt2)[1]; \ } #define PT2D_SUB(Res, Pt1, Pt2) { (Res)[0] = (Pt1)[0] - (Pt2)[0]; \ (Res)[1] = (Pt1)[1] - (Pt2)[1]; \ } #define PT2D_SWAP(Pt1, Pt2) { SWAP(RealType, (Pt1)[0], (Pt2)[0]); \ SWAP(RealType, (Pt1)[1], (Pt2)[1]); \ } #define PT2D_PT2D_DIST(Pt1, Pt2) sqrt(SQR((Pt1)[0] - (Pt2)[0]) + \ SQR((Pt1)[1] - (Pt2)[1])) #define PT2D_PT2D_DIST_SQR(Pt1, Pt2) (SQR((Pt1)[0] - (Pt2)[0]) + \ SQR((Pt1)[1] - (Pt2)[1])) #define VEC_COPY(VDest, VSrc) PT_COPY(VDest, VSrc) #define VEC_SCALE(V, Scalar) PT_SCALE(V, Scalar) #define VEC_SCALE2(Res, V, Scalar) PT_SCALE2(Res, V, Scalar) #define VEC_SQR_LENGTH(V) PT_SQR_LENGTH(V) #define VEC_LENGTH(V) PT_LENGTH(V) #define VEC_RESET(V) PT_RESET(V) #define VEC_NORMALIZE(V) PT_NORMALIZE(V) #define VEC_SAFE_NORMALIZE(V) PT_SAFE_NORMALIZE(V) #define VEC_SET(V, V1, V2, V3) PT_SET(V, V1, V2, V3) #define VEC_BLEND(VRes, V1, V2, t) PT_BLEND(VRes, V1, V2, t) #define VEC_ADD(VRes, V1, V2) PT_ADD(VRes, V1, V2) #define VEC_SUB(VRes, V1, V2) PT_SUB(VRes, V1, V2) #define VEC_SWAP(V1, V2) PT_SWAP(V1, V2) /* Now the same thing but for 2D vectors. */ #define VEC2D_COPY(VDest, VSrc) PT2D_COPY(VDest, VSrc) #define VEC2D_SCALE(V, Scalar) PT2D_SCALE(V, Scalar) #define VEC2D_SCALE2(Res, V, Scalar) PT2D_SCALE2(Res, V, Scalar) #define VEC2D_SQR_LENGTH(V) PT2D_SQR_LENGTH(V) #define VEC2D_LENGTH(V) PT2D_LENGTH(V) #define VEC2D_RESET(V) PT2D_RESET(V) #define VEC2D_NORMALIZE(V) PT2D_NORMALIZE(V) #define VEC2D_SAFE_NORMALIZE(V) PT2D_SAFE_NORMALIZE(V) #define VEC2D_SET(V, V1, V2, V3) PT2D_SET(V, V1, V2, V3) #define VEC2D_BLEND(VRes, V1, V2, t) PT2D_BLEND(VRes, V1, V2, t) #define VEC2D_ADD(VRes, V1, V2) PT2D_ADD(VRes, V1, V2) #define VEC2D_SUB(VRes, V1, V2) PT2D_SUB(VRes, V1, V2) #define VEC2D_SWAP(V1, V2) PT2D_SWAP(V1, V2) #define UV_COPY(UVDst, UVSrc) GEN_COPY(UVDst, UVSrc, 2 * sizeof(RealType)) #define UV_RESET(Uv) ZAP_MEM((Uv), 2 * sizeof(RealType)) #define UV_BLEND(UVRes, UV1, UV2, t) \ { (UVRes)[0] = (UV1)[0] * t + (UV2)[0] * (1 - t); \ (UVRes)[1] = (UV1)[1] * t + (UV2)[1] * (1 - t); \ } #define VEC_BLEND_BARYCENTRIC(Res, Pt1, Pt2, Pt3, W) \ PT_BLEND_BARYCENTRIC(Res, Pt1, Pt2, Pt3, W) #define DOT_PROD(Pt1, Pt2) ((Pt1)[0] * (Pt2)[0] + \ (Pt1)[1] * (Pt2)[1] + \ (Pt1)[2] * (Pt2)[2]) #define CROSS_PROD(PtRes, Pt1, Pt2) \ { (PtRes)[0] = (Pt1)[1] * (Pt2)[2] - (Pt1)[2] * (Pt2)[1]; \ (PtRes)[1] = (Pt1)[2] * (Pt2)[0] - (Pt1)[0] * (Pt2)[2]; \ (PtRes)[2] = (Pt1)[0] * (Pt2)[1] - (Pt1)[1] * (Pt2)[0]; } #define DOT_PROD_2D(Pt1, Pt2) ((Pt1)[0] * (Pt2)[0] + (Pt1)[1] * (Pt2)[1]) #define CROSS_PROD_2D(Pt1, Pt2) ((Pt1)[0] * (Pt2)[1] - (Pt1)[1] * (Pt2)[0]) #define LIST_PUSH(New, List) { (New) -> Pnext = (List); (List) = (New); } #define LIST_POP(Head, List) { (Head) = (List); \ (List) = (List) -> Pnext; \ (Head) -> Pnext = NULL; } #define LIST_LAST_ELEM(Elem) { if (Elem) \ while ((Elem) -> Pnext) \ (Elem) = (Elem) -> Pnext; } #define DEG2RAD_CNVRT 0.0174532925199432957692 #define RAD2DEG_CNVRT 57.2957795130823208768 #define DEG2RAD(Deg) ((Deg) * DEG2RAD_CNVRT) #define RAD2DEG(Rad) ((Rad) * RAD2DEG_CNVRT) #if defined(__WINNT__) && defined(WINNT_LOCAL_THREAD_VARS) # define STATIC_DATA __declspec(thread) static # define GLOBAL_DATA __declspec(thread) #else # define STATIC_DATA static # define GLOBAL_DATA #endif /* __WINNT__ */ #if defined(_AIX) || defined(sgi) || defined(SUN4) || defined(DJGCC) || defined(OS2GCC) || defined(__WINNT__) || defined(__WINCE__) || defined(AMIGA) || defined(_INCLUDE_HPUX_SOURCE) || defined(OSF1DEC) || defined(__FreeBSD__) || defined(__osf__) || defined(_AlphaLinux) || defined(LINUX386) || defined(__CYGWIN__) # include # if defined(OSF1DEC) || defined(sgi) || defined(SUN4) || defined(OS2GCC) || defined(__FreeBSD__) # ifdef OSF1DEC # ifdef _XOPEN_SOURCE # undef _XOPEN_SOURCE /* For usleep */ # endif /* _XOPEN_SOURCE */ # endif /* OSF1DEC */ # include # endif /* OSF1DEC || sgi || SUN4 || OS2GCC || FreeBSD */ # ifdef __WINNT__ # include # define mkdir(Dir, Permit) mkdir(Dir) # endif /* __WINNT__ */ #else VoidPtr malloc(unsigned int Size); void free(VoidPtr p); char *getenv(char *Name); int atoi(char *str); #endif /* _AIX || sgi || SUN4 || DJGCC || OS2GCC || __WINNT__ || __WINCE__ || AMIGA || _INCLUDE_HPUX_SOURCE || OSF1DEC || __FreeBSD__ || _AlphaLinux || LINUX386 ||__CYGWIN__ */ #ifdef SGI64 /* Machine with 64 bit longs */ # define sizeof(x) ((unsigned int) sizeof(x)) # define strlen(x) ((unsigned int) strlen(x)) #endif /* SGI64 */ #ifdef __WINCE__ # define getenv(Str) NULL # define putenv(Str) # define signal(x, y) # define getcwd(s, l) strcpy(s, ".") # define chdir(s) # define system(s) 0 # define popen(s, rw) fopen(s, rw) # define time(x) 0 # define ctime(x) "" # define unlink(s) # define strerror(x) 0 # define time_t int #else # include #endif /* __WINCE__ */ #endif /* IRIT_SM_H */