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

Scene.cc

Go to the documentation of this file.
00001 /*
00002     File:           Scene.cc
00003 
00004     Function:       See header file
00005 
00006     Author(s):      Andrew Willmott
00007 
00008     Copyright:      (c) 1995-2000, Andrew Willmott
00009 
00010     Notes:          
00011 
00012 */
00013 
00014 #include "gcl/Scene.h"
00015 #include "gcl/Avars.h"
00016 #include <iomanip.h>
00017 #include "gcl/VecUtil.h"
00018 #include "gcl/SceneObjects.h"
00019 #include "gcl/ParseSL.h"
00020 
00021 //  'gAttributeNameTable' is a Table for the names of the various attributes.
00022 //  Should be more extendable than this...
00023 
00024 Char *gAttributeNameTable[] =
00025 {
00026     "State",
00027     "Colour",
00028     "Emittance",
00029 
00030     "Points",
00031     "Colours",
00032     "Normals",
00033     "Texture Coordinates",
00034 
00035     "Point Indexes",
00036     "Colour Indexes",
00037     "Normal Indexes",
00038     "TexCoord Indexes",
00039 
00040     "Faces",
00041     "Mesh Type",
00042 
00043     "Transformation",
00044     "Camera",
00045     "Texture",
00046     "ObjHide",
00047     "Avar List",
00048     0
00049 };
00050 
00051 
00052 /*
00053   Notes on polygonal data:
00054 
00055   The scene format is made up of a number of layers, with defaults
00056 
00057   points/colours/normals lists: contain the actual data.
00058 
00059   if there exist indexes/cindexes/nindexes lists, these contain indices
00060   into the most recent entity lists; if not, the indexes are assumed to
00061   read 1, 2, 3, ...
00062 
00063   if there is a faces list, it is assumed to define polygonal faces by
00064   the range of indices into the indexes lists. If not, the lists are
00065   assumed to define a single face.
00066 
00067   (i)   points a, b, c
00068         points c, d, a
00069 
00070   (ii)  points a, b, c, d
00071         indexes 0, 1, 2
00072         indexes 2, 3, 0
00073 
00074   (iii) points a, b, c, d
00075         indexes 0, 1, 2, 2, 3, 0
00076         faces 0,3,6
00077 
00078   for this trivial example, (ii) and (iii) might not seem that useful. For
00079   a large model, with a number of different vertex properties (points, 
00080   surface normals, texture coordinates, etc.) they provide more
00081   flexibility and space savings.
00082 
00083 */
00084 
00085 
00086 // --- scObject methods -------------------------------------------------------
00087 
00088 
00089 scObject::~scObject()
00090 {
00091 }
00092 
00093 Void scObject::Apply(const Transform &m)
00094 {
00095 }
00096 
00097 Void scObject::ApplyAction(scSceneAction &a)
00098 {   
00099     a.Start();
00100     ApplyActionSelf(a);
00101     a.Stop();
00102 }
00103 
00104 Void scObject::ApplyActionSelf(scSceneAction &a)
00105 {   
00106     if (IsAttr())
00107         a.Attribute(AttrCast(this));
00108     else if (IsPrim())
00109         a.Primitive(PrimCast(this));
00110 }
00111 
00112 Void scObject::Print(ostream &s) const
00113 {
00114     s << "Undefined object";
00115 }
00116 
00117 Void scObject::HierPrint(ostream &s, Int indent) const
00118 {
00119     Int i;
00120     
00121     for (i = 0; i < indent; i++)
00122         s << ' ';
00123         
00124     Print(s);
00125     
00126     s << endl;
00127 }
00128 
00129 Void scObject::Decimate(Decimator &dec, UInt32 flags)
00130 {
00131     SLContext       context(aNumAttributes);
00132 
00133     dec.decNum = 0;
00134     dec.pointsAccNum = 0;
00135     dec.transAcc = vl_I;
00136     dec.flags.Clear();
00137     dec.flags.Set(flags);
00138     dec.context = &context;
00139 
00140     if (flags & DecUseMaster)
00141         dec.pointsAcc = new PointList;
00142     else
00143         dec.pointsAcc = 0;
00144 
00145     dec.HandlePoly(DEC_Start, 0, false);
00146     DecimateSelf(dec);
00147     dec.HandlePoly(DEC_End, 0, false);
00148 }
00149 
00150 
00151 // --- Printing operator ------------------------------------------------------
00152 
00153 
00154 Int scObject::prIndent = 4;
00155 
00156 ostream &operator << (ostream &s, const scScenePtr scene)
00157 {
00158     scene->HierPrint(s, 0); // Start from 0 indentation
00159     
00160     return(s);
00161 }
00162 
00163 
00164 // --- scAttribute methods ----------------------------------------------------
00165 
00166 
00167 Void scAttribute::Print(ostream &s) const
00168 {
00169     s << "set " << gAttributeNameTable[AttrID()] << " [" << (Int) AttrID() << "]";
00170 }
00171 
00172 Void scAttribute::AddToContext(SLContext *context)
00173 {
00174     context->Set(AttrID(), this);
00175 }
00176 
00177 Bool scAttribute::HasAvar(Avar &avar, Int slot)
00178 {
00179     return(false);
00180 }
00181 
00182 #ifdef UNFINISHED
00183 Bool scAttribute::HasAvars(Avar &avar, Int slot)
00184 {
00185     rotSlot = list.RegisterAvar("rotate_c");
00186     list.RegisterAvar("rotate_c");
00187     list.RegisterAvar("rotate_c");
00188     return(false);
00189 }
00190 #endif
00191 
00192 Void scClearAttr::Print(ostream &s) const
00193 {
00194     s << "clear " << gAttributeNameTable[AttrID()] << " [" 
00195       << (Int) AttrID() << "]";
00196 }
00197 
00198 Void scClearAttr::AddToContext(SLContext *context)
00199 {
00200     context->Set(AttrID(), 0);
00201 }
00202 
00203 
00204 // --- scPrimitive methods ----------------------------------------------------
00205 
00206 
00207 RenderStyle scPrimitive::sRenderStyle = renPoly;
00208 Colour scPrimitive::sDefaultColour(cOrange);
00209 
00210 Void scPrimitive::Draw(Renderer &r)
00211 {
00212     SLContext context(aNumAttributes);
00213 
00214     context.Clear();
00215 
00216     Draw(r, &context);
00217 }
00218 
00219 Void scPrimitive::Draw(Renderer &r, SLContext *context)
00220 {
00221 }
00222 
00223 Void scPrimitive::Print(ostream &s) const
00224 {
00225     s << Label();
00226 }
00227 
00228 Void scPrimitive::Apply(const Transform& m)
00229 {
00230 }
00231 
00232 Void scPrimitive::Set(scAttribute *sa)
00233 {
00234     Assert(false, "can't set attribute of a non-group.");
00235     if (parent)
00236     {
00237         Int i;
00238 
00239         for (i = 0; i < parent->NumChildren(); i++)
00240             if (parent->Child(i) == this)
00241             {
00242                 parent->children.Insert(i, sa);
00243                 return;
00244             }
00245 
00246         _Error("Bad parent pointer...");
00247     }
00248     else
00249         Assert(false, "can't set attribute of a parentless primitive.");
00250 }
00251 
00252 scAttribute *scPrimitive::Get(scAttributeID searchID)
00253 {
00254     Int i;
00255     scAttribute *result = 0;
00256     
00257     if (parent == 0)
00258         return(0);
00259         
00260     for (i = 0; i < parent->NumChildren(); i++)
00261         if (parent->Child(i)->AttrID() == searchID)
00262             result = AttrCast(parent->Child(i));
00263         else if (parent->Child(i) == this)
00264             break;
00265     
00266     if (result == 0)
00267         return(parent->Get(searchID));  
00268     else
00269         return(result);
00270 }
00271 
00272 scAttribute *scPrimitive::FindFirst(scAttributeID id)
00273 {
00274     return(0);
00275 }
00276 
00277 Void scPrimitive::Normalise()
00278 {
00279     Point   min, max;
00280     GCLReal scale;
00281     Vector  centre; 
00282 
00283     // scale so longest dimension is 1
00284     // center on y axis such that bottom of object touches z-x plane.
00285 
00286     FindBounds(min, max);
00287     scale = MaxElt(max - min) / 2.0;
00288     centre = (min + max) * 0.5;
00289     centre[vl_y] -= (max[vl_y] - min[vl_y]) * 0.5;
00290     Apply(xform(Scalef(1.0 / scale), Shift(-centre)));
00291 }
00292 
00293 Void scPrimitive::FindBounds(Point &min, Point &max)
00294 {
00295     min.MakeBlock(HUGE_VAL);
00296     max.MakeBlock(-HUGE_VAL);
00297     UpdateBounds(min, max, vl_I);
00298 }
00299 
00300 Void scPrimitive::UpdateBounds(Point &min, Point &max,
00301                                const Transform &t)
00302 {
00303 }
00304 
00305 Void scPrimitive::ExtDispatch(Int method, Void *data)
00306 {
00307     if (method == -1)
00308         cerr << "ExtDispatch called, data = " << data << endl;
00309 }
00310 
00311 // --- scGroup methods --------------------------------------------------------
00312 
00313 scGroup::scGroup(const scGroup &sg) : 
00314     scPrimitive(sg), 
00315     children(sg.children),
00316     name(sg.name)
00317 {
00318     int i;
00319     
00320     for (i = 0; i < children.NumItems(); i++)
00321         if (Child(i)->IsPrim())
00322             PrimCast(Child(i))->parent = this;
00323 }
00324 
00325 Void scGroup::ApplyActionSelf(scSceneAction &a)
00326 {   
00327     if (a.context->Get(aObjHide)) return;
00328 
00329     Int         i;
00330     Transform   saveAcc;
00331 
00332     a.context->Push();
00333     saveAcc = a.transAcc;
00334 
00335     for (i = 0; i < NumChildren(); i++)
00336         Child(i)->ApplyActionSelf(a);
00337 
00338     a.transAcc = saveAcc;
00339     a.context->Pop();
00340 }
00341 
00342 Void scGroup::Apply(const Transform &m)
00343 {
00344     children.Prepend(new scTransform(m));
00345 }
00346 
00347 Void scGroup::UpdateBounds(Vector &min, Vector &max, 
00348                            const Transform &transform)
00349 {
00350     Int         i, j;
00351     Transform   groupTransform(transform);
00352 
00353     // should change this to call attr->UpdateBounds?
00354     
00355     for (i = 0; i < NumChildren(); i++)
00356         if (Child(i)->IsAttr())
00357         {
00358             if (Child(i)->AttrID() == aTransform)
00359             {
00360                 groupTransform = xform(groupTransform,
00361                                        (scTransform &) *AttrCast(Child(i)));
00362             }
00363             else if (Child(i)->AttrID() == aPoints)
00364             {
00365                 PointList *pl = (scPoints*) AttrCast(Child(i));
00366                 for (j = 0; j < pl->NumItems(); j++)
00367 					::UpdateBounds(xform(groupTransform, (*pl)[j]), min, max);
00368             }
00369         }
00370         else
00371             PrimCast(Child(i))->UpdateBounds(min, max, groupTransform);
00372 }
00373 
00374 Void scGroup::SetName(StrConst newName)
00375 {
00376     name = newName;
00377 }
00378 
00379 Void scGroup::Add(scObject *so)
00380 {
00381     if (so->IsPrim())
00382         PrimCast(so)->parent = this;
00383     children.Append(so);
00384 }
00385 
00386 scObject *scGroup::Last()
00387 {
00388     return((scObject *) children.Top());
00389 }
00390 
00391 StrConst scGroup::Label() const
00392 {
00393     return(name);
00394 }
00395 
00396 Void scGroup::Print(ostream &s) const
00397 {
00398     HierPrint(s, 0);    // Start from 0 indentation
00399 }
00400 
00401 Void scGroup::DecimateSelf(Decimator &dec)
00402 {
00403     if (dec.context->Get(aObjHide)) return;
00404 
00405     Int         i, j, k, savePointsAccNum;
00406     Transform   saveTransAcc;
00407 
00408     // push current state.
00409     dec.context->Push();
00410     saveTransAcc = dec.transAcc;
00411     savePointsAccNum = dec.pointsAccNum;
00412 
00413     for (i = 0; i < NumChildren(); i++)
00414         if (Child(i)->IsPrim())
00415             PrimCast(Child(i))->DecimateSelf(dec);
00416         else
00417         {
00418             AttrCast(Child(i))->AddToContext(dec.context);
00419 
00420             if (Child(i)->AttrID() == aPoints && (dec.flags.IsSet(DecUseMaster)))
00421             {
00422                 PointList   *points;
00423             
00424                 // need to append this to the master points list
00425                 points = (scPoints*) AttrCast(Child(i));
00426                 // save the current end of the list as the new numbering
00427                 // offset.
00428                 dec.pointsAccNum = dec.pointsAcc->NumItems();
00429                 dec.pointsAcc->Add(points->NumItems());
00430                 // apply the current model transform to the new points
00431                 k = dec.pointsAccNum;
00432                 for (j = 0; j < points->NumItems(); j++)
00433                     (*dec.pointsAcc)[k++] = xform(dec.transAcc,
00434                                                      (*points)[j]);
00435             }
00436             else
00437             {
00438                 // if it's a transform, concatenate it to transAcc
00439                 if (Child(i)->AttrID() == aTransform)
00440                     dec.transAcc = xform(dec.transAcc,
00441                         *(scTransform*)(dec.context->Get(aTransform)));
00442             }
00443         }
00444 
00445     // pop current state.
00446     dec.context->Pop();
00447     dec.transAcc = saveTransAcc;
00448     dec.pointsAccNum = savePointsAccNum;
00449 }
00450 
00451 Void scGroup::HierPrint(ostream &s, Int indent) const
00452 {   
00453     Int     i, j;
00454 
00455     for (j = 0; j < indent; j++)
00456         s << ' ';
00457     s << "object \"";
00458     if (name) 
00459         s << name;
00460     s << "\"" << endl; // " << (Void *) this << ' ' << (Void *) parent << endl; 
00461     
00462     for (i = 0; i < NumChildren(); i++)
00463         Child(i)->HierPrint(s, indent + prIndent);
00464         
00465     for (j = 0; j < indent; j++)
00466         s << ' ';
00467 
00468     s << "end" << endl;
00469 }
00470 
00471 
00472 Void scGroup::Parse(istream &s)
00473 {
00474     Char        c;
00475     scObject    *newObj;
00476     String      *str = new String;
00477         
00478     while (isspace(s.peek()))               //  chomp white space
00479         s.get(c);
00480         
00481     s >> *str;
00482     *str = SubstituteEnvVars(*str);
00483 
00484     name = str->Ref();
00485     
00486     children.Clear();
00487         
00488     while (1)
00489     {           
00490         newObj = ParseSLObject(s);
00491         if (newObj == 0)
00492             break;
00493         if (!s)
00494         {
00495             Expect(false, "Couldn't read object component");
00496             return;
00497         }
00498 
00499         Add(newObj);
00500     }           
00501 }
00502 
00503 Object *scGroup::Clone() const
00504 {
00505     Int i;
00506     scGroup *result;
00507         
00508     result = new scGroup(name);
00509     
00510     for (i = 0; i < children.NumItems(); i++)
00511         result->Add((scObject*) children[i]->Clone());
00512                 
00513     return(result);
00514 }
00515 
00516 #include "gcl/SceneObjects.h"
00517 
00518 Void scGroup::Draw(Renderer &r, SLContext *context)
00519 {
00520     if (context->Get(aObjHide)) return;
00521 
00522     Int     i;
00523     
00524     r.Push();
00525     context->Push();
00526     
00527     for (i = 0; i < NumChildren(); i++)
00528         if (Child(i)->IsPrim())
00529             PrimCast(Child(i))->Draw(r, context);
00530         else
00531         {
00532             // ignore cameras other than the first one
00533             if (Child(i)->AttrID() == aCamera && context->Get(aCamera))
00534                 continue;
00535 
00536             AttrCast(Child(i))->AddToContext(context);
00537             if (Child(i)->AttrID() == aTransform)
00538                 r.SetTransform((scTransform &) *AttrCast(Child(i)));
00539             else if (Child(i)->AttrID() == aCamera)
00540                 r.SetCamera((scCamera &) *AttrCast(Child(i)));
00541         }
00542             
00543     context->Pop();
00544     r.Pop();
00545 }
00546 
00547 Void scGroup::Set(scAttribute *sa)
00548 {
00549     Int     i;
00550 
00551 #ifdef UNFINISHED
00552     for (i = 0; i < NumChildren() && Child(i)->IsAttr(); i++)
00553         if (Child(i)->AttrID() == sa->AttrID())
00554         {
00555             Child(i)->Free();
00556             children[i] = sa;
00557             return;
00558         }
00559 #endif
00560         
00561     children.Prepend(sa);
00562 }
00563 
00564 scAttribute *scGroup::FindFirst(scAttributeID id)
00565 {
00566 //  if (!on) return(0); XXX
00567     
00568     Int         i;
00569     scAttribute *result;
00570     
00571     for (i = 0; i < NumChildren(); i++)
00572         if (Child(i)->IsPrim())
00573         {
00574             result = PrimCast(Child(i))->FindFirst(id);
00575             if (result)
00576                 return(result);
00577         }
00578         else if (Child(i)->AttrID() == id)
00579                 return(AttrCast(Child(i)));
00580                 
00581     return(0);
00582 }
00583 
00584 // --- Actions ----------------------------------------------------------------
00585 
00586 
00595 Void scSceneAction::Start()
00596 {
00597     transAcc = vl_I;
00598     context = new SLContext(aNumAttributes);
00599 }
00600 
00601 Void scSceneAction::Stop()
00602 {
00603     delete context;             
00604     context = 0;
00605 }
00606 
00607 Void scSceneAction::Primitive(scPrimitive *sp)
00608 {
00609 }
00610 
00611 Void scSceneAction::Attribute(scAttribute *sa)
00612 {
00613     sa->AddToContext(context);
00614 }
00615 
00616 
00617 // --- Avar methods/operators -------------------------------------------------
00618 
00619 
00620 ostream  &operator << (ostream &s, const Avar &avar)
00621 {
00622     s << avar.name << " [" << avar.lowerBound << " " << avar.value << " " <<
00623         avar.upperBound << "]";
00624     
00625     return(s);
00626 }
00627 
00628 
00629 // --- extras -----------------------------------------------------------------
00630 
00631 Void FindDecInfo::HandlePoly(
00632         Int         numVertices,
00633         Int         vertices[],
00634         Int         changed
00635     )
00636 {   
00637     if (numVertices == DEC_Start)
00638     {
00639         numProps = 0;
00640         numTris = 0;
00641         numQuads = 0;
00642         numPolys = 0;
00643     }
00644     
00645     if (numVertices < 0) return;
00646 
00647     if (changed)
00648         numProps++;
00649     
00650     if (numVertices == 3)
00651         numTris++;
00652     else if (numVertices == 4)
00653         numQuads++;
00654 
00655     numPolys++;
00656 }

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