// Copyright (C) 1997 Keith Whitwell. // This file may only be copied under the terms of the GNU Library General // Public License - see the file COPYING in the lib3d distribution. // This file is contributed by // Markus F.X.J. Oberhumer #include #include #include /*********************************************************************** // ************************************************************************/ // don't pollute the global namespace #define ModelParser PlgReaderModelParser class ModelParser : public Debuggable { public: ModelParser(istream &in_, int line_ = 0) : in(in_), line(line_), comment(0) { } virtual char *getline(char *buf, int len); virtual char *getline(); virtual char *stripWhitespace(char *s); virtual char *stripComment(char *s); virtual void setComment(const char *s) { comment = s; } virtual int lineNr() const { return line; } operator istream&() { return in; } operator const istream&() const { return in; } protected: istream ∈ int line; const char *comment; char buffer[1024]; }; char * ModelParser::getline(char *buf, int len) { char *p; while (!in.eof()) { in.getline(buf,len); line++; p = buf; p = stripWhitespace(p); p = stripComment(p); if (*p) { return p; } } return 0; } char * ModelParser::getline() { return getline(buffer,sizeof(buffer)); } char * ModelParser::stripWhitespace(char *s) { // remove trailing whitespace char *p = s + strlen(s); while (p > s && isspace(((unsigned char) p[-1]))) *--p = 0; // remove leading whitespace p = s; while (*p && isspace(((unsigned char) *p))) p++; return p; } char * ModelParser::stripComment(char *s) { if (comment && *comment && s && *s && strchr(comment,*s)) *s = 0; return s; } /*********************************************************************** // Reader for .PLG files as distributed with REND386/VR-386/AVRIL. ************************************************************************/ static bool setPLGMaterial ( uint plgColour, Material &m ) { static const unsigned char plg_pal[ 3*256 ] = { 0, 0, 0, 0, 0, 170, 0, 170, 0, 0, 170, 170, 170, 0, 0, 170, 0, 170, 170, 85, 0, 170, 170, 170, 85, 85, 85, 85, 85, 255, 85, 255, 85, 85, 255, 255, 255, 85, 85, 255, 85, 255, 255, 255, 85, 255, 255, 255, 65, 0, 0, 73, 0, 0, 81, 0, 0, 89, 0, 0, 97, 0, 0, 105, 0, 0, 113, 0, 0, 121, 0, 0, 134, 0, 0, 146, 0, 0, 158, 0, 0, 170, 0, 0, 186, 0, 0, 207, 0, 0, 227, 0, 0, 251, 0, 0, 65, 32, 0, 73, 36, 0, 81, 40, 0, 89, 40, 0, 97, 44, 0, 105, 48, 0, 113, 56, 0, 121, 60, 0, 134, 65, 0, 146, 69, 0, 158, 77, 0, 170, 81, 0, 186, 89, 0, 207, 101, 0, 227, 109, 0, 251, 121, 0, 65, 32, 32, 73, 36, 36, 81, 40, 40, 89, 40, 40, 97, 44, 44, 105, 48, 48, 113, 56, 56, 121, 60, 60, 134, 65, 65, 146, 69, 69, 158, 77, 77, 170, 81, 81, 186, 89, 89, 207, 101, 101, 227, 109, 109, 251, 121, 121, 65, 48, 32, 73, 56, 36, 81, 60, 40, 89, 65, 40, 97, 73, 44, 105, 77, 48, 113, 85, 56, 121, 89, 60, 134, 97, 65, 146, 109, 69, 158, 117, 77, 170, 125, 81, 186, 138, 89, 207, 154, 101, 227, 170, 109, 251, 186, 121, 65, 65, 32, 73, 73, 36, 81, 81, 40, 89, 89, 40, 97, 97, 44, 105, 105, 48, 113, 113, 56, 121, 121, 60, 134, 134, 65, 146, 146, 69, 158, 158, 77, 170, 170, 81, 186, 186, 89, 207, 207, 101, 227, 227, 109, 251, 251, 121, 65, 65, 0, 73, 73, 0, 81, 81, 0, 89, 89, 0, 97, 97, 0, 105, 105, 0, 113, 113, 0, 121, 121, 0, 134, 134, 0, 146, 146, 0, 158, 158, 0, 170, 170, 0, 186, 186, 0, 207, 207, 0, 227, 227, 0, 251, 251, 0, 0, 65, 32, 0, 73, 36, 0, 81, 40, 0, 89, 40, 0, 97, 44, 0, 105, 48, 0, 113, 56, 0, 121, 60, 0, 134, 65, 0, 146, 69, 0, 158, 77, 0, 170, 81, 0, 186, 89, 0, 207, 101, 0, 227, 109, 0, 251, 121, 0, 65, 0, 0, 73, 0, 0, 81, 0, 0, 89, 0, 0, 97, 0, 0, 105, 0, 0, 113, 0, 0, 121, 0, 0, 134, 0, 0, 146, 0, 0, 158, 0, 0, 170, 0, 0, 186, 0, 0, 207, 0, 0, 227, 0, 0, 251, 0, 0, 65, 48, 0, 73, 56, 0, 81, 60, 0, 89, 65, 0, 97, 73, 0, 105, 77, 0, 113, 85, 0, 121, 89, 0, 134, 97, 0, 146, 109, 0, 158, 117, 0, 170, 125, 0, 186, 138, 0, 207, 154, 0, 227, 170, 0, 251, 186, 0, 48, 65, 0, 56, 73, 0, 60, 81, 0, 65, 89, 0, 73, 97, 0, 77, 105, 0, 85, 113, 0, 89, 121, 0, 97, 134, 0, 109, 146, 0, 117, 158, 0, 125, 170, 0, 138, 186, 0, 154, 207, 0, 170, 227, 0, 186, 251, 0, 0, 65, 0, 0, 73, 0, 0, 81, 0, 0, 89, 0, 0, 97, 0, 0, 105, 0, 0, 113, 0, 0, 121, 0, 0, 134, 0, 0, 146, 0, 0, 158, 0, 0, 170, 0, 0, 186, 0, 0, 207, 0, 0, 227, 0, 0, 251, 65, 0, 65, 73, 0, 73, 81, 0, 81, 89, 0, 89, 97, 0, 97, 105, 0, 105, 113, 0, 113, 121, 0, 121, 134, 0, 134, 146, 0, 146, 158, 0, 158, 170, 0, 170, 186, 0, 186, 207, 0, 207, 227, 0, 227, 251, 0, 251, 65, 0, 48, 73, 0, 56, 81, 0, 60, 89, 0, 65, 97, 0, 73, 105, 0, 77, 113, 0, 85, 121, 0, 89, 134, 0, 97, 146, 0, 109, 158, 0, 117, 170, 0, 125, 186, 0, 138, 207, 0, 154, 227, 0, 170, 251, 0, 186, 32, 32, 32, 36, 36, 36, 40, 40, 40, 44, 44, 44, 48, 48, 48, 52, 52, 52, 56, 56, 56, 60, 60, 60, 65, 65, 65, 73, 73, 73, 77, 77, 77, 85, 85, 85, 93, 93, 93, 105, 105, 105, 113, 113, 113, 125, 125, 125, 65, 65, 65, 73, 73, 73, 81, 81, 81, 89, 89, 89, 97, 97, 97, 105, 105, 105, 113, 113, 113, 121, 121, 121, 134, 134, 134, 146, 146, 146, 158, 158, 158, 170, 170, 170, 186, 186, 186, 207, 207, 207, 227, 227, 227, 255, 255, 255 }; uint hilite = plgColour & 0xF000; /* highlight flag (MSB) */ uint bright = plgColour & 0xFF; /* albedo */ uint hue = (plgColour & 0x0F00) >> 4; /* basis color */ uint colour = 0; Vector3 col; float Ka = 0.3; float Kd = 1.0; float c1 = 0.0; float c2 = 0.0; float c3 = 0.0; if (hue == 0) colour = hilite | bright; else colour = hilite | hue | ((bright >> 4) & 0x0F) ; if ((plgColour & 0x3000) == 0x0000) { /* fixed (unlit) colour */ Ka = 1.0; } else if ((plgColour & 0x3000) == 0x1000) { /* cosine lit */ Ka = 0.3; } #if 0 else return false; #endif uint i = (colour & 0xff) * 3; col.assign(plg_pal[i]/255.0, plg_pal[i+1]/255.0, plg_pal[i+2]/255.0); m.setParameters(col, Ka, Kd, c1, c2, c3); return true; } bool PLGReader::readPLG( istream &in ) { ModelParser mp(in); calculatePolygonNormals(); calculateVertexNormals(); setPolygonMaterial( 0 ); setSearchBehaviour( Vertices, false ); int i; int lastVert = vertices.getNr(); const char *p = 0; char name[255]; int nrVert; int nrPoly; int nrPolyVert = -1; uint *vnum = 0; bool multi = false; uint errorMat = addMaterial(Vector3(1.0,0.0,0.0), 0.3,1.0, 0,0,0); mp.setComment("*"); p = mp.getline(); mp.setComment("*#"); if (p && strstr(p,"#MULTI")) { multi = true; p = mp.getline(); } else if (p && *p == '#') { p = mp.getline(); } if (!p || sscanf(p, "%s %d %d %d", name, &nrVert, &nrPoly, &nrPolyVert) < 3) goto error; // cerr << name << " " << nrVert << " " << nrPoly << endl; for (i = 0; i < nrVert; i++) { Vector3 v; p = mp.getline(); if (!p || sscanf(p, "%f %f %f", &v.v[X], &v.v[Y], &v.v[Z]) != 3) goto error; // cerr << v.v[X] << v.v[Y] << v.v[Z] << endl; v.v[Y] = -v.v[Y]; addVertex(v); } for (i = 0; i < nrPoly; i++) { int n, j; uint plgColour; int nrPoint; p = mp.getline(); if (!p || ( sscanf(p, "%x%n", &plgColour, &n) != 1 && sscanf(p, "%X%n", &plgColour, &n) != 1 && sscanf(p, "%d%n", &plgColour, &n) != 1)) goto error; p += n; if (sscanf(p, "%d%n", &nrPoint, &n) != 1) goto error; p += n; // cerr << plgColour << " " << nrPoint << endl; if (nrPoint < 2) goto error; uint *vnum = new uint[nrPoint]; for (j = 0; j < nrPoint; j++) { int vn; if (sscanf(p, "%d%n", &vn, &n) != 1) goto error; // cerr << j << " " << vn << " " << n << endl; p += n; if (vn < 0 || vn >= nrVert) goto error; vnum[j] = vn + lastVert; } if (!colourfulMode) { Material m; uint idx = errorMat; if (setPLGMaterial(plgColour, m)) { idx = addMaterial(m); if (idx == (uint)(~0)) idx = errorMat; } setPolygonMaterial(idx); } if (addPolygon(nrPoint, vnum) == (uint)(~0)) goto error; delete[] vnum; vnum = 0; } return true; error: if (vnum) delete[] vnum; cerr << "Error in line " << mp.lineNr() << ": " << p << endl; return false; }