Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

SceneObjects.cc

Go to the documentation of this file.
00001 /*
00002     File:       SceneObjects.cc
00003 
00004     Function:   See header file
00005 
00006     Author:     Andrew Willmott
00007 
00008     Notes:      
00009 */
00010 
00011 #include "gcl/SceneObjects.h"
00012 #include "gcl/VecUtil.h"
00013 #include "gcl/GCLConfig.h"
00014 
00015 // --- Polygon methods --------------------------------------------------------
00016     
00017 StrConst scPoly::Label() const
00018 {
00019     return("mesh");
00020 }
00021 
00022 IndexList *gIdentityList = 0;
00023 
00024 
00025 /*
00026     Current defaults:
00027 
00028     point indexes = [0, 1, 2, 3...]
00029     normal, texture indexes: point indexes
00030     colour indexes: normal indexes
00031 */
00032 
00033 Void scPoly::Draw(Renderer &r, SLContext *context)
00034 // draw one or more polygons
00035 {
00036     Int         i, j;
00037     Int         f, faces, faceS, faceE;
00038     Vector      normal;
00039     Colour      polyClr;
00040     PointList   *points;
00041     NormalList  *normals;
00042     ColourList  *colours;
00043     CoordList   *coords;
00044     Texture     *texture;
00045     IndexList   *indexes;
00046     IndexList   *clrIndexes;
00047     IndexList   *normIndexes;
00048     IndexList   *coordIndexes;
00049     IndexList   *faceIndexes;
00050     scMeshType  *meshType;
00051     RenderStyle meshStyle;
00052     
00053     points = SC_GET(Points);
00054     colours = SC_GET(Colours);
00055     normals = SC_GET(Normals);
00056     texture = SC_GET(Texture);
00057 
00058     if (!gIdentityList)
00059     {
00060         gIdentityList = new IndexList(256);
00061         for (i = 0; i < gIdentityList->NumItems(); i++)
00062             gIdentityList->Item(i) = i;
00063     }
00064 
00065     indexes = SC_GET(PointIndexes);
00066     faceIndexes = SC_GET(FaceIndexes);
00067     if (meshType = SC_GET(MeshType))
00068         meshStyle = meshType->itsType;
00069     else
00070         meshStyle = sRenderStyle;
00071 
00072     if (!indexes)
00073     {
00074         indexes = gIdentityList;
00075         Assert(points->NumItems() <= 256, "polygon too large");
00076         // note: we are relying on Array not changing the current items
00077         // array when we resize down and then back up again. 
00078         // (This is currently safe: the items array only changes if the array
00079         // size is increased.)
00080         indexes->SetSize(points->NumItems());
00081     }
00082 
00083     normIndexes = SC_GET(NormalIndexes);
00084     if (!normIndexes)
00085         normIndexes = indexes;
00086 
00087     if (colours)
00088     {
00089         clrIndexes = SC_GET(ColourIndexes);
00090         if (!clrIndexes)
00091             clrIndexes = normIndexes;
00092     }
00093     else
00094     {
00095         if (SC_GET(Colour))
00096             polyClr = *(SC_GET(Colour));
00097         else if (SC_GET(Emittance))
00098             polyClr = *(SC_GET(Emittance));
00099         else
00100             polyClr[0] = -1.0;
00101     }
00102             
00103     if (texture)
00104     {
00105         // texture map
00106         coords = SC_GET(Coords);
00107         if (coords)
00108         {
00109             r.SetTexture(texture->image);
00110             coordIndexes = SC_GET(CoordIndexes);
00111             if (!coordIndexes)
00112                 coordIndexes = gIdentityList;
00113         }
00114     }
00115     else 
00116         coords = 0;
00117         
00118     if (faceIndexes)
00119     {
00120 
00121         if (faceIndexes->NumItems() < 2)
00122         {
00123             // XXX empty face index list
00124             // should modify face begin & end routines to cull
00125             // such empty lists; requires object->Remove() method?
00126 //          _Warning("Empty face index list");
00127             return;
00128         }
00129         
00130         faceS = faceIndexes->Item(0);
00131         faceE = faceIndexes->Item(1);
00132         faces = faceIndexes->NumItems() - 1;
00133         f = 2;
00134     }
00135     else
00136     {
00137         faceS = 0;
00138         faceE = indexes->NumItems();
00139         faces = 1;
00140     }
00141             
00142     while (true)
00143     {
00144         r.Begin(meshStyle);
00145 
00146         if (!normals)
00147         {
00148             CalcTriAreaNormal((*points)[(*indexes)[faceS]], 
00149                 (*points)[(*indexes)[faceS + 1]], 
00150                 (*points)[(*indexes)[faceS + 2]], 
00151                 normal
00152             );
00153             r.N(normal);
00154         }
00155         
00156         if (!colours && polyClr[0] >= 0.0)
00157             r.SetColour(polyClr);
00158                 
00159         for (i = faceS; i < faceE; i++)
00160         {
00161             if (colours)
00162             {
00163                 j = (*clrIndexes)[i];
00164                 r.SetColour((*colours)[j]);
00165             }
00166             if (coords)
00167             {
00168                 j = (*coordIndexes)[i];
00169                 r.SetTexCoord((*coords)[j]);
00170             }
00171             if (normals)
00172             {
00173                 j = (*normIndexes)[i];
00174                 r.SetNormal((*normals)[j]);
00175             }
00176                 
00177             j = (*indexes)[i];
00178             r.SetPoint((*points)[j]);
00179         }
00180         r.End();
00181 
00182         if (faces <= 1) break;
00183         faces--;
00184         faceS = faceE;
00185         faceE = faceIndexes->Item(f++);
00186     }
00187 
00188     if (coords)
00189         r.SetTexture(0);
00190 }
00191 
00192 Void scPoly::DecimateSelf(Decimator &dec)
00193 {
00194     Int         i, j, n, idx[32], changed;
00195     Int         fi, fStart, fEnd, fLen;
00196     SLContext   *context = dec.context;
00197     PointList   *points = SC_GET(Points);
00198     IndexList   *indexes = SC_GET(PointIndexes);
00199     IndexList   *faces = SC_GET(FaceIndexes);
00200 
00201     if (!points)
00202         return;
00203 
00204     if (!indexes)
00205     {
00206         if (!gIdentityList)
00207         {
00208             gIdentityList = new IndexList(256);
00209             for (i = 0; i < gIdentityList->NumItems(); i++)
00210                 gIdentityList->Item(i) = i;
00211         }
00212         indexes = gIdentityList;
00213         Assert(points->NumItems() <= 256, "polygon too large");
00214         // note: we are relying on Array not changing the current items
00215         // array when we resize down and then back up again. 
00216         // (This is currently safe: the items array only changes if the array
00217         // size is increased.)
00218         indexes->SetSize(points->NumItems());
00219     }
00220 
00221     changed = 1;
00222     if (faces)
00223     {
00224         fStart = (*faces)[0];
00225         fEnd = (*faces)[1];
00226         fLen = fEnd - fStart;
00227         fi = 2;
00228     }
00229     else
00230     {
00231         fStart = 0;
00232         fLen = fEnd = indexes->NumItems();
00233     }
00234 
00235     while (true)
00236     {
00237         if (!(dec.flags & DecTris))
00238             n = fLen;
00239         else if (fLen == 4 && (dec.flags & DecQuads))
00240         {
00241             // XXX : not stable as height of pgram goes to zero.
00242             
00243             Int     *ip = &(*indexes)[fStart];
00244             Vector  ab = (*points)[ip[1]] - (*points)[ip[0]];
00245             Vector  cd = (*points)[ip[2]] - (*points)[ip[3]];
00246 
00247             // ab == cd : |ab - cd| / |ab + cd| < eps?
00248 
00249             if (sqrlen(ab - cd) / sqrlen(ab + cd) < 1e-6)
00250                 n = 4;
00251             else
00252                 n = 3;
00253         }
00254         else
00255             n = 3;
00256 
00257         for (j = 0; j < n; j++)
00258             idx[j] = (*indexes)[j + fStart] + dec.pointsAccNum;
00259                         
00260         dec.HandlePoly(n, idx, changed);
00261         dec.decNum++;
00262         changed = 0;
00263         
00264         if (n == 3)
00265             for (j = fStart + 2; j < fEnd - 1; j++)
00266             {
00267                 idx[1] = (*indexes)[j] + dec.pointsAccNum;
00268                 idx[2] = (*indexes)[j + 1] + dec.pointsAccNum;
00269                 dec.HandlePoly(n, idx, 0);
00270                 dec.decNum++;
00271             }
00272 
00273         if (faces && fi < faces->NumItems())
00274         {
00275             fStart = fEnd;
00276             fEnd = (*faces)[fi++];
00277             fLen = fEnd - fStart;
00278         }
00279         else
00280             break;
00281     }
00282 }
00283 
00284 Void scPoly::Parse(istream &s)
00285 {
00286 }
00287 
00288 
00289 // --- Attributes -------------------------------------------------------------
00290     
00291 Void scPoints::Apply(const Transform &m)
00292 {
00293     Int i;
00294     
00295     for (i = 0; i < NumItems(); i++)
00296         SELF[i] = proj(xform(m, Vector4(SELF[i], 1.0)));
00297 }
00298 
00299 Void scCoords::Apply(const Transform &m)
00300 {
00301 }
00302 
00303 Void scTransform::ApplyActionSelf(scSceneAction &a)
00304 {
00305     scObject::ApplyActionSelf(a);
00306     a.transAcc = xform(a.transAcc, SELF);
00307 }
00308 
00309 Void scCamera::Parse(istream &s)
00310 {
00311     String  str;
00312     Vector  p;
00313     Char    c;
00314     Int     model = 1;
00315 
00316     ChompWhiteSpace(s);
00317     while (s.peek() == '+')                 // extension?
00318     {
00319         s.get(c);
00320         str.ReadWord(s);
00321 
00322         if (str == "eye")
00323             s >> position;
00324         else if (str == "dir")
00325             s >> viewDir;
00326         else if (str == "lookAt")
00327         {
00328             s >> lookAt;
00329             model = 2;
00330         }
00331         else if (str == "vup")
00332             s >> up;
00333         else if (str == "scale")
00334             s >> scale;
00335         else if (str == "fov")
00336             s >> fov;
00337         else if (str == "clipNear")
00338             s >> clipNear;
00339         else if (str == "clipFar")
00340             s >> clipFar;
00341         else
00342             cerr << "unknown camera option: '" << str << "'" << endl;
00343         
00344         ChompWhiteSpace(s);
00345     }
00346 
00347     SetupFromParams();
00348 }
00349 
00350 Void scCamera::Print(ostream &s) const
00351 {
00352 //  GetViewDirParams();     XXX can't do this 'cause of const
00353     
00354     s << "camera";
00355     
00356     if (scale != 1.0)
00357         s << " +scale " << scale;
00358 
00359     s << " +eye " << position;
00360     s << " +dir " << viewDir;
00361     s << " +vup " << up;
00362     s << " +fov " << fov;
00363 }
00364 
00365 Void scIndexes::Print(ostream &s) const
00366 {
00367     switch (AttrID())
00368     {
00369     case aPointIndexes:
00370         s << "indexes ";
00371         break;
00372     case aNormalIndexes:
00373         s << "n_indexes ";
00374         break;
00375     case aCoordIndexes:
00376         s << "t_indexes ";
00377         break;
00378     case aColourIndexes:
00379         s << "c_indexes ";
00380         break;
00381     case aFaceIndexes:
00382         s << "faces ";
00383         break;
00384     }
00385     
00386     s << (IndexList&) SELF << endl;
00387 }
00388 
00389 Void scTexture::Parse(istream &s)
00390 {
00391     String str;
00392     
00393     ChompWhiteSpace(s);
00394     s >> str;
00395     Load(str);
00396 }
00397 
00398 Void scTexture::Print(ostream &s) const
00399 {
00400     s << "texture \"" << textureFile.GetPath() << '"';
00401 }
00402 
00403 Void scMeshType::Parse(istream &s)
00404 {
00405     String str;
00406     
00407     ChompWhiteSpace(s);
00408 //  s >> itsType;
00409 }
00410 
00411 Void scMeshType::Print(ostream &s) const
00412 {
00413     s << "meshtype \"" << itsType << '"';
00414 }
00415 

Generated at Sat Aug 5 00:17:03 2000 for Graphics Class Library by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000