home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Virtual Reality Zone
/
VRZONE.ISO
/
mac
/
PC
/
REND386
/
CONVERT
/
IRIT2PLG
/
IRIT2PLG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-29
|
18KB
|
580 lines
/* Here it is. Assuming you have irit 3.0, cd to the iritfltr directory, edit
makefile.tc, insert an entry irit2plg similar to irit2ray, and
'make -f makefile.tc'
Gershon
*/
/*****************************************************************************
* Filter to convert IRIT data files to REND386 (IBMPC only) Plg format. *
* *
* Written by: Gershon Elber Ver 1.0, Sep 1991 *
*****************************************************************************/
#ifdef __MSDOS__
#include <dos.h>
#include <alloc.h>
#endif /* __MSDOS__ */
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include "irit_sm.h"
#include "iritprsr.h"
#include "getarg.h"
#include "genmat.h"
#define GLOBAL_SCALE 200.0 /* Scale obj space -1..1 to -200..200 pixels. */
#define CONVEX_EPSILON 1e-3
#ifdef __MSDOS__
extern unsigned int _stklen = 32766; /* Increase default stack size. */
#endif /* __MSDOS__ */
#ifdef NO_CONCAT_STR
static char *VersionStr =
"Irit2Plg Version 3.0, Gershon Elber,\n\
(C) Copyright 1989/90/91/92 Gershon Elber, Non commercial use only.";
#else
static char *VersionStr = "Irit2Plg " VERSION ", Gershon Elber, "
__DATE__ ", " __TIME__ "\n"
"(C) Copyright 1989/90/91/92 Gershon Elber, Non commercial use only.";
#endif /* NO_CONCAT_STR */
static char
*CtrlStr = "irit2Plg l%- 4%- f%-FineNess!d z%- DFiles!*s";
static int
GlblFineNess = 5,
FourPerFlat = FALSE;
static MatrixType CrntViewMat; /* This is the current view! */
static int TransColorTable[][4] = {
{ /* BLACK */ 0, 0, 0, 0 },
{ /* BLUE */ 1, 0, 0, 255 },
{ /* GREEN */ 2, 0, 255, 0 },
{ /* CYAN */ 3, 0, 255, 255 },
{ /* RED */ 4, 255, 0, 0 },
{ /* MAGENTA */ 5, 255, 0, 255 },
{ /* BROWN */ 6, 50, 0, 0 },
{ /* LIGHTGRAY */ 7, 127, 127, 127 },
{ /* DARKGRAY */ 8, 63, 63, 63 },
{ /* LIGHTBLUE */ 9, 0, 0, 255 },
{ /* LIGHTGREEN */ 10, 0, 255, 0 },
{ /* LIGHTCYAN */ 11, 0, 255, 255 },
{ /* LIGHTRED */ 12, 255, 0, 0 },
{ /* LIGHTMAGENTA */ 13, 255, 0, 255 },
{ /* YELLOW */ 14, 255, 255, 0 },
{ /* WHITE */ 15, 255, 255, 255 },
{ /* BROWN */ 20, 50, 0, 0 },
{ /* DARKGRAY */ 56, 63, 63, 63 },
{ /* LIGHTBLUE */ 57, 0, 0, 255 },
{ /* LIGHTGREEN */ 58, 0, 255, 0 },
{ /* LIGHTCYAN */ 59, 0, 255, 255 },
{ /* LIGHTRED */ 60, 255, 0, 0 },
{ /* LIGHTMAGENTA */ 61, 255, 0, 255 },
{ /* YELLOW */ 62, 255, 255, 0 },
{ /* WHITE */ 63, 255, 255, 255 },
{ -1, 0, 0, 0 }
};
static int PlgColorTable[16] = {
/* IRIT PLG */
15, /* BLOCK -> WHITE */
11, /* BLUE */
7, /* GREEN */
8, /* CYAN */
1, /* RED */
13, /* MAGENTA */
2, /* BROWN */
14, /* LIGHTGRAY */
14, /* DARKGRAY */
10, /* LIGHT BLUE */
9, /* LIGHT GREEN */
8, /* LIGHT CYAN */
1, /* LIGHT RED */
13, /* LIGHT MAGENTA */
6, /* YELLOW */
15, /* WHITE */
};
static IPObjectStruct *MainGetDataFiles(char **DataFileNames,
int NumOfDataFiles);
static IPPolygonStruct *Surface2Polygons(CagdSrfStruct *Srf, int FourPerFlat,
int FineNess);
static void DumpDataForPlg(IPObjectStruct *PObjects);
static void DumpOneObject(FILE *f, IPObjectStruct *PObject,
int DumpVertices, int *IncVertices);
static void DumpOnePolygon(FILE *f, IPPolygonStruct *PPolygon,
int Color, int DumpVertices, int *IncVertices);
static int IsConvexPolygon(IPPolygonStruct *Pl);
static RealType *MapPoint(RealType *Pt);
static void MyExit(int ExitCode);
/*****************************************************************************
* Main routine - Read Parameter line and do what you need... *
*****************************************************************************/
void main(int argc, char **argv)
{
int Error,
FineNessFlag = FALSE,
LinearOnePolyFlag = FALSE,
VerFlag = FALSE,
NumFiles = 0;
char
**FileNames = NULL;
IPObjectStruct *PObjects;
#ifdef __MSDOS__
ctrlbrk((int (*)()) MyExit); /* Kill process if ^C. */
#endif /* __MSDOS__ */
if ((Error = GAGetArgs (argc, argv, CtrlStr, &LinearOnePolyFlag,
&FourPerFlat, &FineNessFlag, &GlblFineNess,
&VerFlag, &NumFiles, &FileNames)) != 0) {
GAPrintErrMsg(Error);
GAPrintHowTo(CtrlStr);
MyExit(1);
}
if (VerFlag) {
fprintf(stderr, "\n%s\n\n", VersionStr);
GAPrintHowTo(CtrlStr);
MyExit(0);
}
if (LinearOnePolyFlag) {
fprintf(stderr, "Linear patch side will have a single polygon.\n");
CagdSetLinear2Poly(CAGD_ONE_POLY_PER_COLIN);
}
else
CagdSetLinear2Poly(CAGD_REG_POLY_PER_LIN);
fprintf(stderr, "%s triangles per flat will be created.\n",
FourPerFlat ? "Four" : "Two");
if (!NumFiles) {
fprintf(stderr, "No data file names where given, exit.\n");
GAPrintHowTo(CtrlStr);
MyExit(1);
}
/* Get the data files: */
IritPrsrPolyListCirc = FALSE;
PObjects = MainGetDataFiles(FileNames, NumFiles);
if (IritPrsrWasPrspMat)
MultTwo4by4(CrntViewMat, IritPrsrViewMat, IritPrsrPrspMat);
else
GEN_COPY(CrntViewMat, IritPrsrViewMat, sizeof(MatrixType));
DumpDataForPlg(PObjects);
MyExit(0);
}
/*****************************************************************************
* Main routine to read the data description files: *
* Returns pointer to pointers on FileDescription structures (one per file). *
*****************************************************************************/
static IPObjectStruct *MainGetDataFiles(char **DataFileNames,
int NumOfDataFiles)
{
int i;
FILE *f;
char
*ErrorMsg = NULL;
IPObjectStruct *PObj, *PObjTail,
*PObjHead = NULL;
for (i = 0; i < NumOfDataFiles; i++) {
#ifdef __MSDOS__
if ((f = fopen(*DataFileNames, "rt")) == NULL) { /* Open the file. */
#else
if ((f = fopen(*DataFileNames, "r")) == NULL) { /* Open the file. */
#endif /* __MSDOS__ */
fprintf(stderr, "Can't open data file %s\n", *DataFileNames);
MyExit(1);
}
if ((PObj = IritPrsrGetObjects(f)) != NULL) { /* Get the data file. */
PObjTail = PObj;
while (PObjTail -> Pnext) PObjTail = PObjTail -> Pnext;
PObjTail -> Pnext = PObjHead;
PObjHead = PObj;
}
fclose(f); /* Close the file. */
if (IritPrsrParseError(&ErrorMsg)) {
fprintf(stderr, "Parse error in \"%s\":\n%s\n", *DataFileNames, ErrorMsg);
MyExit(1);
}
DataFileNames++; /* Skip to next file name. */
}
if (PObjHead == NULL) {
fprintf(stderr, "No data found.\n");
MyExit(1);
}
return PObjHead;
}
/*****************************************************************************
* Routine to convert all surfaces/curves into polylines as follows: *
* Curves are converted to single polyline with SamplesPerCurve samples. *
* Surface are converted into GlblNumOfIsolines curves in each axes, each *
* handled as Curves above. The curves and surfaces are then deleted. *
*****************************************************************************/
IPObjectStruct *IritPrsrProcessFreeForm(IPObjectStruct *CrvObjs,
IPObjectStruct *SrfObjs)
{
int LocalFourPerFlat;
float RelativeFineNess;
CagdCrvStruct *Crvs;
CagdSrfStruct *Srf, *Srfs;
IPObjectStruct *PObj, *PObjNext;
IPPolygonStruct *PPolygon, *PPolygonTemp;
if (CrvObjs == NULL && SrfObjs == NULL) return NULL;
/* Make sure requested format is something reasonable. */
if (GlblFineNess < 2) {
GlblFineNess = 2;
fprintf(stderr, "FineNess is less than 2, 2 picked instead.\n");
}
if (CrvObjs) {
/* Curves are not rendered at this time and they are ignored. */
for (PObj = CrvObjs; PObj != NULL;) {
Crvs = PObj -> U.PCrvs;
CagdCrvFreeList(Crvs);
PObjNext = PObj -> Pnext;
free((VoidPtr) PObj);
PObj = PObjNext;
}
CrvObjs = NULL;
}
if (SrfObjs) {
for (PObj = SrfObjs; PObj != NULL; PObj = PObj -> Pnext) {
char *p;
Srfs = PObj -> U.PSrfs;
PObj -> U.PPolygon = NULL;
PObj -> Type = IP_OBJ_POLY;
RelativeFineNess = 1.0;
LocalFourPerFlat = FourPerFlat;
if (IritPrsrGetStrAttrib(PObj, "twoperflat"))
LocalFourPerFlat = FALSE;
if (IritPrsrGetStrAttrib(PObj, "fourperflat"))
LocalFourPerFlat = TRUE;
if ((p = IritPrsrGetStrAttrib(PObj, "resolution")) != NULL &&
sscanf(p, "%f", &RelativeFineNess) != 1)
RelativeFineNess = 1.0;
for (Srf = Srfs; Srf != NULL; Srf = Srf -> Pnext) {
PPolygon = PPolygonTemp =
Surface2Polygons(Srf, LocalFourPerFlat,
(int) (RelativeFineNess * GlblFineNess));
while (PPolygonTemp -> Pnext)
PPolygonTemp = PPolygonTemp -> Pnext;
PPolygonTemp -> Pnext = PObj -> U.PPolygon;
PObj -> U.PPolygon = PPolygon;
}
CagdSrfFreeList(Srfs);
}
}
return SrfObjs;
}
/*****************************************************************************
* Routine to convert a single surface into a polylines with SamplesPerCurve *
* samples, NumOfIsolines isolines into a polyline object list. *
*****************************************************************************/
static IPPolygonStruct *Surface2Polygons(CagdSrfStruct *Srf, int FourPerFlat,
int FineNess)
{
int i, j;
IPVertexStruct *V, *VHead,
*VTail = NULL;
IPPolygonStruct *P,
*PHead = NULL;
CagdPolygonStruct *CagdPolygon,
*CagdPolygonHead = CagdSrf2Polygons(Srf, FineNess, TRUE, FourPerFlat);
for (CagdPolygon = CagdPolygonHead, VHead = NULL;
CagdPolygon != NULL;
CagdPolygon = CagdPolygon -> Pnext) {
/* All polygons are triangles! */
for (i = 0, VHead = NULL; i < 3; i++) { /* Convert to vertices. */
V = IritPrsrNewVertexStruct();
IP_SET_VRTX_NORMAL(V); /* This vertex has normal. */
for (j = 0; j < 3; j++) /* Convert to our format. */
V -> Coord[j] = CagdPolygon -> Polygon[i].Pt[j];
for (j = 0; j < 3; j++)
V -> Normal[j] = CagdPolygon -> Normal[i].Vec[j];
if (VHead) {
VTail -> Pnext = V;
VTail = V;
}
else
VHead = VTail = V;
}
P = IritPrsrNewPolygonStruct();
P -> PVertex = VHead;
P -> Type = IP_POLYGON;
P -> Pnext = PHead;
PHead = P;
}
CagdPolygonFreeList(CagdPolygonHead);
return PHead;
}
/*****************************************************************************
* Dumps the data for REND386 Plg into stdout. *
*****************************************************************************/
static void DumpDataForPlg(IPObjectStruct *PObjects)
{
int IncVertices,
TotalVertices = 0,
TotalPolys = 0;
char
*Name = NULL;
IPVertexStruct *PVertex;
IPPolygonStruct *PPoly;
IPObjectStruct *PObj,
*PObjHead = NULL;
FILE *f = stdout; /* Change it if you want it into "real" file. */
/* Reverse object list since it was loaded in reverse by iritprsr module.*/
while (PObjects != NULL) {
PObj = PObjects;
PObjects = PObjects -> Pnext;
PObj -> Pnext = PObjHead;
PObjHead = PObj;
}
PObjects = PObjHead;
/* Count how many polygons/vertices we have in this data set and print. */
for (PObj = PObjects; PObj != NULL; PObj = PObj -> Pnext) {
if (PObj -> Type != IP_OBJ_POLY) {
fprintf(stderr, "Wrong input, a poly was expected.\n");
exit(1);
}
if (Name == NULL && strlen(PObj -> Name) > 0) Name = PObj -> Name;
for (PPoly = PObj -> U.PPolygon;
PPoly != NULL;
PPoly = PPoly -> Pnext) {
if (PPoly -> Type != IP_POLYGON) continue;
TotalPolys++;
for (PVertex = PPoly -> PVertex;
PVertex != NULL;
PVertex = PVertex -> Pnext) {
TotalVertices++;
}
}
}
if (Name != NULL)
fprintf(f, "IRIT %d %d\n", TotalVertices, TotalPolys);
else
fprintf(f, "%s_IRIT %d %d\n", Name, TotalVertices, TotalPolys);
for (IncVertices = 0, PObj = PObjects; PObj != NULL; PObj = PObj -> Pnext)
DumpOneObject(f, PObjects, TRUE, &IncVertices);
if (IncVertices != TotalVertices) {
fprintf(stderr, "Inconsistent vertices count.\n");
exit(1);
}
for (IncVertices = 0, PObj = PObjects; PObj != NULL; PObj = PObj -> Pnext)
DumpOneObject(f, PObjects, FALSE, &IncVertices);
if (IncVertices != TotalVertices) {
fprintf(stderr, "Inconsistent vertices count.\n");
exit(1);
}
fclose(f);
}
/*****************************************************************************
* Routine to dump one object PObject. *
*****************************************************************************/
static void DumpOneObject(FILE *f, IPObjectStruct *PObject,
int DumpVertices, int *IncVertices)
{
int i, Color;
IPPolygonStruct
*PList = PObject -> U.PPolygon;
if (IP_HAS_OBJ_COLOR(PObject)) {
for (i = 0; TransColorTable[i][0] >= 0; i++) {
if (TransColorTable[i][0] == PObject -> Color) {
Color = PlgColorTable[i];
break;
}
}
}
else
Color = 15; /* Default to white. */
while (PList) {
DumpOnePolygon(f, PList, Color, DumpVertices, IncVertices);
PList = PList -> Pnext;
}
}
/*****************************************************************************
* Routine to dump one polygon, using global Matrix transform CrntViewMat. *
*****************************************************************************/
static void DumpOnePolygon(FILE *f, IPPolygonStruct *PPolygon,
int Color, int DumpVertices, int *IncVertices)
{
int CountVertices;
RealType *MappedPoint;
IPVertexStruct *V,
*VList = PPolygon -> PVertex;
if (VList == NULL) return;
if (DumpVertices && !IsConvexPolygon(PPolygon)) {
static int Printed = FALSE;
if (!Printed) {
fprintf(stderr,
"Non convex polygon(s) may be in data (see CONVEX in IRIT).\n");
Printed = TRUE;
}
}
switch (PPolygon -> Type) {
case IP_POLYGON:
if (DumpVertices) {
for (V = VList; V != NULL; V = V -> Pnext) {
MappedPoint = MapPoint(V -> Coord);
fprintf(f, "%4d %4d %4d\n",
(int) (MappedPoint[0] * GLOBAL_SCALE),
(int) (MappedPoint[1] * GLOBAL_SCALE),
(int) (MappedPoint[2] * GLOBAL_SCALE));
(*IncVertices)++;
}
}
else {
for (CountVertices = 0, V = VList; V != NULL; V = V -> Pnext)
CountVertices++;
fprintf(f, "0x%02xff %d", Color | 0x0010, CountVertices);
while (CountVertices-- > 0)
fprintf(f, " %d", (*IncVertices)++);
fprintf(f, "\n");
}
break;
}
}
/*****************************************************************************
* Routine to test if the given polygon is convex or not. *
* Algorithm: The polygon is convex iff the normals generated from cross *
* products of two consecutive edges points to the same direction. The same *
* direction is tested by a positive dot product. *
*****************************************************************************/
static int IsConvexPolygon(IPPolygonStruct *Pl)
{
RealType Size, V1[3], V2[3], LastNormal[3], Normal[3];
IPVertexStruct *VNext, *VNextNext,
*V = Pl -> PVertex;
LastNormal[0] = LastNormal[1] = LastNormal[2] = 0.0;
do {
if ((VNext = V -> Pnext) == NULL)
VNext = Pl -> PVertex;
if ((VNextNext = VNext -> Pnext) == NULL)
VNextNext = Pl -> PVertex;
PT_SUB(V1, VNext -> Coord, V -> Coord);
if ((Size = PT_LENGTH(V1)) > EPSILON) {
Size = 1.0 / Size;
PT_SCALE(V1, Size);
}
PT_SUB(V2, VNextNext -> Coord, VNext -> Coord);
if ((Size = PT_LENGTH(V2)) > EPSILON) {
Size = 1.0 / Size;
PT_SCALE(V2, Size);
}
CROSS_PROD(Normal, V1, V2);
if (V != Pl -> PVertex) {
if (PT_LENGTH(Normal) > CONVEX_EPSILON &&
DOT_PROD(Normal, LastNormal) < -CONVEX_EPSILON)
return FALSE;
}
PT_COPY(LastNormal, Normal);
V = VNext;
}
while (V != Pl -> PVertex && V != NULL);
return TRUE;
}
/*****************************************************************************
* Maps the given E3 point using the CrntViewMat. *
*****************************************************************************/
static RealType *MapPoint(RealType *Pt)
{
static RealType MappedPt[3];
MultVecby4by4(MappedPt, Pt, CrntViewMat);
return MappedPt;
}
/*****************************************************************************
* Trap Cagd_lib errors right here. *
*****************************************************************************/
void CagdFatalError(CagdFatalErrorType ErrID)
{
char
*ErrorMsg = CagdDescribeError(ErrID);
fprintf(stderr, "CAGD_LIB: %s", ErrorMsg);
exit(-1);
}
/*****************************************************************************
* MyExit routine. Note it might call to CloseGraph without calling *
* InitGraph(), or call MouseClose() without MouseInit() etc. and it is the *
* responsibility of the individual modules to do nothing in these cases. *
*****************************************************************************/
static void MyExit(int ExitCode)
{
#ifdef __MSDOS__
fprintf(stderr,
"\nIrit2Plg: Core left %ldk.\n", coreleft() / 1024);
#endif /* __MSDOS__ */
exit(ExitCode);
}