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

HierMesh.cc

Go to the documentation of this file.
00001 /*
00002     File:           HierMesh.cc
00003 
00004     Function:       See header file
00005 
00006     Author(s):      Andrew Willmott
00007 
00008     Copyright:      (c) 1997-2000, Andrew Willmott
00009 
00010     Notes:          
00011 
00012 */
00013 
00014 #include "HierMesh.h"
00015 #include "cl/String.h"
00016 #include "gcl/VecUtil.h"
00017 
00018 // --- Internal routines ------------------------------------------------------
00019 
00020 static Void PrintCode(ostream &s, Int level, Int treeCode);
00021 
00022 
00070 // --- Constructors -----------------------------------------------------------
00071 
00072 
00073 HierElem::HierElem() : parent(0), level(0), NbRadElem()
00074 {
00075     Int i;
00076     
00077     treeCode = 0;
00078     for (i = 0; i < 4; i++)
00079         child[i] = 0;
00080 }
00081 
00082 HierElem::~HierElem()
00083 {
00084     FreeChildren();
00085 }
00086 
00087 static Int tQuadDirToCh1[] = { 0, 1, 2, 3 };
00088 // Tables to find children in a certain direction for quad
00089 static Int tQuadDirToCh2[] = { 1, 2, 3, 0 };
00090 // e.g., the two children in dir 1 (west) are 0 and 2    
00091 
00092 static Int tTriDirToCh1[] = { 0, 1, 2 };
00093 // Tables to find children in a certain direction for triangle
00094 static Int tTriDirToCh2[] = { 1, 2, 0 };
00095 // e.g., the two children in dir 0 (north west) are 0 and 1 
00096  
00097 Void HierElem::FreeChildren()
00098 {
00099     if (HasChildren())
00100         for (Int i = 0; i < 4; i++)
00101         {
00102             delete child[i];
00103             child[i] = 0;
00104         }
00105 }
00106 
00107 Void HierElem::ConnectNeighbours()
00108 {
00109     Int         i, ch2, ch2o, oppDir;
00110     HierElem    **nc;
00111     
00112     if (IsQuad())
00113     {
00114         // Make neighbour connections between children.
00115         child[0]->nbFace[1] = child[1];     
00116         child[0]->nbFace[2] = child[3];
00117         child[1]->nbFace[3] = child[0];
00118         child[1]->nbFace[2] = child[2];
00119         child[2]->nbFace[3] = child[3];
00120         child[2]->nbFace[0] = child[1];
00121         child[3]->nbFace[0] = child[0];
00122         child[3]->nbFace[1] = child[2];
00123 
00124         child[0]->nbEdge[1] = 3;        
00125         child[0]->nbEdge[2] = 0;
00126         child[1]->nbEdge[3] = 1;
00127         child[1]->nbEdge[2] = 0;
00128         child[2]->nbEdge[3] = 1;
00129         child[2]->nbEdge[0] = 2;
00130         child[3]->nbEdge[0] = 2;
00131         child[3]->nbEdge[1] = 3;
00132 
00133         for (i = 0; i < 4; i++)                                 
00134         // iterate over the directions...
00135             if (NbFace(i) && NbFace(i)->HasChildren())  
00136             // do we have a neighbour with children?
00137             {
00138                 nc = NbFace(i)->child;
00139                 oppDir = nbEdge[i];
00140                 ch2 = tQuadDirToCh2[i];
00141                 ch2o = tQuadDirToCh2[oppDir];
00142                 
00143                 //  notify neighbour's children that they have new neighbours...
00144             
00145                 nc[oppDir]->nbFace[oppDir] = child[ch2];
00146                 nc[ch2o]->nbFace[oppDir] = child[i];
00147                 nc[oppDir]->nbEdge[oppDir] = i;
00148                 nc[ch2o]->nbEdge[oppDir] = i;
00149                 
00150                 //  & vice-versa
00151             
00152                 child[i]->nbFace[i] = nc[ch2o];
00153                 child[ch2]->nbFace[i] = nc[oppDir];
00154                 child[i]->nbEdge[i] = oppDir;
00155                 child[ch2]->nbEdge[i] = oppDir;
00156             }
00157     }
00158     else    // IsTri()
00159     {
00160         child[0]->nbFace[1] = child[3];
00161         child[1]->nbFace[2] = child[3];
00162         child[2]->nbFace[0] = child[3];
00163         child[3]->nbFace[0] = child[2];
00164         child[3]->nbFace[1] = child[0];
00165         child[3]->nbFace[2] = child[1];
00166     
00167         child[0]->nbEdge[1] = 1;
00168         child[1]->nbEdge[2] = 2;
00169         child[2]->nbEdge[0] = 0;
00170         child[3]->nbEdge[0] = 0;
00171         child[3]->nbEdge[1] = 1;
00172         child[3]->nbEdge[2] = 2;
00173     
00174         // Make neighbour connections between children and neighbours' children
00175     
00176         for (i = 0; i < 3; i++)                                 
00177         // iterate over the directions...
00178             if (NbFace(i) && NbFace(i)->HasChildren())  
00179             // do we have a neighbour with children?
00180             {
00181                 nc = NbFace(i)->child;
00182                 oppDir = nbEdge[i];
00183                 i = tTriDirToCh1[i];        // our children along this edge
00184                 ch2 = tTriDirToCh2[i];
00185                 ch2o = tTriDirToCh2[oppDir];    // this edge
00186                 
00187                 //  notify neighbour's children that they have new neighbours
00188                 nc[oppDir]->nbFace[oppDir] = child[ch2];
00189                 nc[ch2o]->nbFace[oppDir] = child[i];
00190                 nc[oppDir]->nbEdge[oppDir] = i;
00191                 nc[ch2o]->nbEdge[oppDir] = i;
00192                 
00193                 //  & vice-versa
00194                 child[i]->nbFace[i] = nc[ch2o];
00195                 child[ch2]->nbFace[i] = nc[oppDir];
00196                 child[i]->nbEdge[i] = oppDir;
00197                 child[ch2]->nbEdge[i] = oppDir;
00198             }
00199     }
00200 }
00201 
00202 Void HierElem::Subdivide()
00203 {
00204     Int i;
00205         
00206     // Hand off to our children if we have them...
00207     if (HasChildren())
00208     {
00209         for (i = 0; i < 4; i++)
00210             child[i]->Subdivide();
00211         
00212         return;
00213     }
00214 
00215     RadElem     mid; // to store midpoint indices
00216     Int         ch1o, ch2o, n, oppDir;
00217     HierElem    **nc;
00218         
00219     // Allocate the children
00220     for (i = 0; i < 4; i++)
00221         child[i] = New();
00222 
00223     if (IsQuad())
00224         // store centrepoint of quad in child 0 for now.
00225         props->InterpolateIndexes(this, 0, 2, child[0], 2);
00226         
00227     // Fill in children's indices, creating new midpoints as necessary.
00228     
00229     if (IsTri())
00230     {
00231         for (i = 0; i < 3; i++)
00232         // Iterate over the directions...
00233             if (NbFace(i) && NbFace(i)->HasChildren())  
00234             // Do we have a neighbour with children?
00235             {
00236                 nc = NbFace(i)->child;
00237                 oppDir = nbEdge[i];
00238                 ch1o = tTriDirToCh1[oppDir];
00239                 ch2o = tTriDirToCh2[oppDir];
00240                 
00241                 //  If so, fetch neighbour's midpoint on this edge
00242                 mid.SetIndexes(i, nc[ch1o], ch2o);
00243             }
00244             else
00245             {                   
00246                 //  Otherwise, create a new one.
00247                 props->InterpolateIndexes(
00248                     this,
00249                     tTriDirToCh1[i], tTriDirToCh2[i],
00250                     &mid, i);
00251             }
00252         
00253         child[0]->SetAllIndexes(this, 0, &mid, 0, &mid, 2, this, 3);
00254         child[1]->SetAllIndexes(&mid, 0, this, 1, &mid, 1, this, 3);
00255         child[2]->SetAllIndexes(&mid, 2, &mid, 1, this, 2, this, 3);
00256         child[3]->SetAllIndexes(&mid, 1, &mid, 2, &mid, 0, this, 3);
00257 
00258     }
00259     else    // IsQuad()
00260     {
00261         for (i = 0; i < 4; i++)                                 
00262         // Iterate over the directions...
00263             if (NbFace(i) && NbFace(i)->HasChildren())  
00264             // Do we have a neighbour with children?
00265             {
00266                 nc = NbFace(i)->child;                      
00267                 oppDir = nbEdge[i];
00268                 ch1o = tQuadDirToCh1[oppDir];
00269                 ch2o = tQuadDirToCh2[oppDir];
00270                 
00271                 //  If so, fetch neighbour's midpoint on this edge
00272                 mid.SetIndexes(i, nc[ch1o], ch2o);
00273             }
00274             else
00275             {   
00276                 //  Otherwise, create a new one.
00277                 props->InterpolateIndexes(
00278                     this,
00279                     tQuadDirToCh1[i], tQuadDirToCh2[i],
00280                     &mid, i);
00281             }
00282             
00283         //  Fill in indices.
00284         child[0]->SetAllIndexes(this, 0, &mid, 0, child[0], 2, &mid, 3);
00285         child[1]->SetAllIndexes(&mid, 0, this, 1, &mid, 1, child[0], 2);
00286         child[2]->SetAllIndexes(child[0], 2, &mid, 1, this, 2, &mid, 2);
00287         child[3]->SetAllIndexes(&mid, 3, child[0], 2, &mid, 2, this, 3);
00288     }
00289     
00290     //  Now, fill in the neighbour fields
00291     ConnectNeighbours();
00292     
00293     //  And fill in other useful fields...
00294     for (i = 0; i < 4; i++)
00295     {
00296         child[i]->SetParent(SELF);
00297         child[i]->treeCode = (treeCode << 2) | i;
00298     }
00299         
00300     // Subdivide neighbours to maintain an evenly-graded mesh: each quad is 
00301     // subdivided to within one level of its neighbours.
00302 
00303     if (gRadControl->graded && parent)
00304     {
00305         // If we don't have a neighbour at our level, but our parent has one,
00306         // subdivide it so it's within one level of our (new) children.
00307     
00308         for (i = 0; i < Sides(); i++)
00309             if (!NbFace(i) && parent->NbFace(i))
00310                 parent->NbFace(i)->Subdivide();
00311     }
00312 }
00313 
00314 Void HierElem::Reanimate(RadElem *par)
00315 {
00316     RadElem::Reanimate(parent);
00317     
00318     parent = (HierElem *) par;
00319     if (parent)
00320         SetProps(parent->props);
00321     
00322     if (HasChildren())
00323     {
00324         ConnectNeighbours();
00325         
00326         child[0]->Reanimate(this);
00327         child[1]->Reanimate(this);
00328         child[2]->Reanimate(this);
00329         child[3]->Reanimate(this);
00330     }
00331 }
00332 
00333 Void HierElem::SetParent(HierElem &itsParent)
00334 {
00335     colour = itsParent.colour;
00336     parent = &itsParent;
00337     
00338     level = parent->level + 1;
00339     area = parent->area / 4;
00340     SetProps(parent->props);
00341 }
00342 
00343 Void HierElem::ColourVertices(Int weights[])
00344 {
00345     if (HasChildren())
00346     {
00347         Int i;
00348         
00349         for (i = 0; i < 4; i++)
00350             child[i]->ColourVertices(weights);
00351     }
00352     else
00353     {
00354         Int         i, idx, oppDir, ch2o;     
00355         HierElem    **nc;       
00356         
00357         for (i = 0; i < Sides(); i++)
00358         {
00359             VtxClr(i) += colour;
00360             weights[clrIdx[i]] += 1;
00361         }
00362         
00363         if (IsQuad())
00364         {
00365             // iterate over directions
00366             
00367             for (i = 0; i < 4 ; i++)
00368                 if (NbFace(i) && NbFace(i)->HasChildren())
00369                 // if we have neighbours
00370                 {
00371                     nc = NbFace(i)->child;
00372                     oppDir = nbEdge[i];
00373                     ch2o = tQuadDirToCh2[oppDir];
00374                     
00375                     // find index of neighbouring midcolour.
00376 
00377                     idx = nc[oppDir]->clrIdx[ch2o];
00378                     
00379                     // add in 2 x our colour, because if we were subdivided, 
00380                     // two of our children would contribute to this midpoint.
00381                     
00382                     (*props->colours)[idx] += 2 * colour;
00383                     weights[idx] += 2;
00384                 }
00385         }
00386         else
00387         {
00388             for (i = 0; i < 3 ; i++)
00389                 if (NbFace(i) && NbFace(i)->HasChildren())
00390                 {                   
00391                     nc = NbFace(i)->child;
00392                     oppDir = nbEdge[i];
00393                     ch2o = tTriDirToCh2[oppDir];
00394 
00395                     // find index of neighbouring midcolour.
00396 
00397                     idx = nc[oppDir]->clrIdx[ch2o];
00398     
00399                     // add in 3 x our colour, because if we were subdivided,
00400                     // three of our children would contribute to this midpoint.
00401 
00402                     (*props->colours)[idx] += 3 * colour;
00403                     weights[idx] += 3;
00404                 }
00405         }
00406     }
00407 }
00408 
00409 // --- Anchored drawing routines ----------------------------------------------
00410 
00411 // Not for the faint of heart!
00412 
00413 static Void AE_DrawQuad(Renderer &r, RenderStyle style, 
00414                      RadElem *e0, Int i0,
00415                      RadElem *e1, Int i1,
00416                      RadElem *e2, Int i2,
00417                      RadElem *e3, Int i3
00418     )
00419 {
00420     if (!e0->IsTextured())
00421         r.Begin(style)
00422             .C(e0->VtxClr(i0)).P(e0->Vertex(i0))
00423             .C(e1->VtxClr(i1)).P(e1->Vertex(i1))
00424             .C(e2->VtxClr(i2)).P(e2->Vertex(i2))
00425             .C(e3->VtxClr(i3)).P(e3->Vertex(i3))
00426             .End();
00427     else
00428         r.Begin(style)
00429             .T(e0->TexCoord(i0)).C(e0->VtxClr(i0)).P(e0->Vertex(i0))
00430             .T(e1->TexCoord(i1)).C(e1->VtxClr(i1)).P(e1->Vertex(i1))
00431             .T(e2->TexCoord(i2)).C(e2->VtxClr(i2)).P(e2->Vertex(i2))
00432             .T(e3->TexCoord(i3)).C(e3->VtxClr(i3)).P(e3->Vertex(i3))
00433             .End();
00434 }
00435 
00436 static Void AE_DrawTria(Renderer &r, RenderStyle style, 
00437                      RadElem *e0, Int i0,
00438                      RadElem *e1, Int i1,
00439                      RadElem *e2, Int i2
00440     )
00441 {
00442     if (!e0->IsTextured())
00443         r.Begin(style)
00444             .C(e0->VtxClr(i0)).P(e0->Vertex(i0))
00445             .C(e1->VtxClr(i1)).P(e1->Vertex(i1))
00446             .C(e2->VtxClr(i2)).P(e2->Vertex(i2))
00447             .End();
00448     else
00449         r.Begin(style)
00450             .T(e0->TexCoord(i0)).C(e0->VtxClr(i0)).P(e0->Vertex(i0))
00451             .T(e1->TexCoord(i1)).C(e1->VtxClr(i1)).P(e1->Vertex(i1))
00452             .T(e2->TexCoord(i2)).C(e2->VtxClr(i2)).P(e2->Vertex(i2))
00453             .End();
00454 }
00455 
00456 static Void AE_ProjQuad(Renderer &r, RenderStyle style, 
00457                      RadElem *e0, Int i0,
00458                      RadElem *e1, Int i1,
00459                      RadElem *e2, Int i2,
00460                      RadElem *e3, Int i3
00461     )
00462 {
00463     r.Begin(style); 
00464     e0->RaiseVertex(r, i0);
00465     e1->RaiseVertex(r, i1);
00466     e2->RaiseVertex(r, i2);
00467     e3->RaiseVertex(r, i3);
00468     r.End();
00469 }
00470 
00471 static Void AE_ProjTria(Renderer &r, RenderStyle style, 
00472                      RadElem *e0, Int i0,
00473                      RadElem *e1, Int i1,
00474                      RadElem *e2, Int i2
00475     )
00476 {
00477     r.Begin(style); 
00478     e0->RaiseVertex(r, i0);
00479     e1->RaiseVertex(r, i1);
00480     e2->RaiseVertex(r, i2);
00481     r.End();
00482 }
00483  
00484 #define MP(X) mid, X
00485 #define VP(X) this, X
00486 #define AE_QUAD(A, B, C, D)     AE_DrawQuad(r, style, A, B, C, D)
00487 #define AE_TRIA(A, B, C)        AE_DrawTria(r, style, A, B, C)
00488 
00489 
00490 Void HierElem::DrawQuad(Renderer &r, RenderStyle style, Int code, RadElem *mid)
00491 // Draw a quad with anchoring.
00492 {
00493     switch (code)   // 16 cases for a quad...
00494     {
00495     case 0:
00496         AE_QUAD(VP(1), VP(2), VP(3), VP(0));
00497         break;
00498     case 1:
00499         AE_TRIA(VP(1), MP(3), VP(0));
00500         AE_TRIA(VP(1), VP(2), MP(3));
00501         AE_TRIA(VP(2), VP(3), MP(3));
00502         break;
00503     case 2:
00504         AE_TRIA(VP(0), MP(2), VP(3));
00505         AE_TRIA(VP(0), VP(1), MP(2));
00506         AE_TRIA(VP(1), VP(2), MP(2));
00507         break;
00508     case 3:
00509         AE_TRIA(VP(1), MP(2), MP(3));
00510         AE_TRIA(VP(1), VP(2), MP(2));
00511         AE_TRIA(VP(1), MP(3), VP(0));
00512         AE_TRIA(MP(2), VP(3), MP(3));
00513         break;
00514     case 4:
00515         AE_TRIA(VP(3), MP(1), VP(2));
00516         AE_TRIA(VP(3), VP(0), MP(1));
00517         AE_TRIA(VP(0), VP(1), MP(1));
00518         break;
00519     case 5:
00520         AE_QUAD(VP(1), MP(1), MP(3), VP(0));
00521         AE_QUAD(MP(1), VP(2), VP(3), MP(3));
00522         break;              
00523     case 6:
00524         AE_TRIA(VP(0), MP(1), MP(2));
00525         AE_TRIA(VP(0), VP(1), MP(1));
00526         AE_TRIA(VP(0), MP(2), VP(3));
00527         AE_TRIA(MP(1), VP(2), MP(2));
00528         break;              
00529     case 7:
00530         AE_QUAD(VP(1), MP(1), MP(3), VP(0));
00531         AE_TRIA(MP(1), MP(2), MP(3));
00532         AE_TRIA(MP(1), VP(2), MP(2));
00533         AE_TRIA(MP(2), VP(3), MP(3));
00534         break;              
00535     case 8:
00536         AE_TRIA(VP(2), MP(0), VP(1));
00537         AE_TRIA(VP(2), VP(3), MP(0));
00538         AE_TRIA(VP(3), VP(0), MP(0));
00539         break;              
00540     case 9:
00541         AE_TRIA(VP(2), MP(3), MP(0));
00542         AE_TRIA(VP(2), VP(3), MP(3));
00543         AE_TRIA(VP(2), MP(0), VP(1));
00544         AE_TRIA(MP(3), VP(0), MP(0));
00545         break;              
00546     case 10:
00547         AE_QUAD(VP(2), MP(2), MP(0), VP(1));
00548         AE_QUAD(MP(2), VP(3), VP(0), MP(0));
00549         break;              
00550     case 11:
00551         AE_QUAD(VP(2), MP(2), MP(0), VP(1));
00552         AE_TRIA(MP(2), MP(3), MP(0));
00553         AE_TRIA(MP(2), VP(3), MP(3));
00554         AE_TRIA(MP(3), VP(0), MP(0));
00555         break;              
00556     case 12:
00557         AE_TRIA(VP(3), MP(0), MP(1));
00558         AE_TRIA(VP(3), VP(0), MP(0));
00559         AE_TRIA(VP(3), MP(1), VP(2));
00560         AE_TRIA(MP(0), VP(1), MP(1));
00561         break;              
00562     case 13:
00563         AE_QUAD(VP(3), MP(3), MP(1), VP(2));
00564         AE_TRIA(MP(3), MP(0), MP(1));
00565         AE_TRIA(MP(3), VP(0), MP(0));
00566         AE_TRIA(MP(0), VP(1), MP(1));
00567         break;              
00568     case 14:
00569         AE_QUAD(VP(0), MP(0), MP(2), VP(3));
00570         AE_TRIA(MP(0), MP(1), MP(2));
00571         AE_TRIA(MP(0), VP(1), MP(1));
00572         AE_TRIA(MP(1), VP(2), MP(2));
00573         break;              
00574     case 15:
00575         AE_TRIA(VP(1), MP(1), MP(0));
00576         AE_TRIA(MP(0), MP(3), VP(0));
00577         AE_TRIA(MP(1), VP(2), MP(2));
00578         AE_TRIA(MP(2), VP(3), MP(3));
00579         AE_QUAD(MP(0), MP(1), MP(2), MP(3));
00580         break;              
00581     }
00582 }
00583 
00584 Void HierElem::DrawTri(Renderer &r, RenderStyle style, Int code, RadElem *mid)
00585 {
00586 //  Draw a triangle with anchoring
00587     switch (code)   // 8 cases for a tri...
00588     {
00589     case 0:
00590         AE_TRIA(VP(0), VP(1), VP(2));
00591         break;
00592     case 1:
00593         AE_TRIA(VP(0), VP(1), MP(2));
00594         AE_TRIA(VP(1), VP(2), MP(2));
00595         break;
00596     case 2:
00597         AE_TRIA(VP(0), VP(1), MP(1));
00598         AE_TRIA(MP(1), VP(2), VP(0));
00599         break;
00600     case 3:
00601         AE_QUAD(VP(0), VP(1), MP(1), MP(2));
00602         AE_TRIA(MP(1), VP(2), MP(2));
00603         break;
00604     case 4:
00605         AE_TRIA(VP(0), MP(0), VP(2));
00606         AE_TRIA(MP(0), VP(1), VP(2));
00607         break;
00608     case 5:
00609         AE_TRIA(VP(0), MP(0), MP(2));
00610         AE_QUAD(MP(0), VP(1), VP(2), MP(2));
00611         break;              
00612     case 6:
00613         AE_TRIA(MP(0), VP(1), MP(1));
00614         AE_QUAD(VP(0), MP(0), MP(1), VP(2));
00615         break;              
00616     case 7:
00617         AE_TRIA(VP(0), MP(0), MP(2));
00618         AE_TRIA(MP(0), VP(1), MP(1));
00619         AE_TRIA(MP(2), MP(1), VP(2));
00620         AE_TRIA(MP(0), MP(1), MP(2));
00621         break;              
00622     }
00623 }
00624 
00625 #undef AE_QUAD
00626 #undef AE_TRIA
00627 #define AE_QUAD(A, B, C, D)     AE_ProjQuad(r, style, A, B, C, D)
00628 #define AE_TRIA(A, B, C)        AE_ProjTria(r, style, A, B, C)
00629 
00630 Void HierElem::ProjQuad(Renderer &r, RenderStyle style, Int code, RadElem *mid)
00631 // Projected version of DrawQuad
00632 {
00633     switch (code)   // 16 cases for a quad...
00634     {
00635     case 0:
00636         AE_QUAD(VP(1), VP(2), VP(3), VP(0));
00637         break;
00638     case 1:
00639         AE_TRIA(VP(1), MP(3), VP(0));
00640         AE_TRIA(VP(1), VP(2), MP(3));
00641         AE_TRIA(VP(2), VP(3), MP(3));
00642         break;
00643     case 2:
00644         AE_TRIA(VP(0), MP(2), VP(3));
00645         AE_TRIA(VP(0), VP(1), MP(2));
00646         AE_TRIA(VP(1), VP(2), MP(2));
00647         break;
00648     case 3:
00649         AE_TRIA(VP(1), MP(2), MP(3));
00650         AE_TRIA(VP(1), VP(2), MP(2));
00651         AE_TRIA(VP(1), MP(3), VP(0));
00652         AE_TRIA(MP(2), VP(3), MP(3));
00653         break;
00654     case 4:
00655         AE_TRIA(VP(3), MP(1), VP(2));
00656         AE_TRIA(VP(3), VP(0), MP(1));
00657         AE_TRIA(VP(0), VP(1), MP(1));
00658         break;
00659     case 5:
00660         AE_QUAD(VP(1), MP(1), MP(3), VP(0));
00661         AE_QUAD(MP(1), VP(2), VP(3), MP(3));
00662         break;              
00663     case 6:
00664         AE_TRIA(VP(0), MP(1), MP(2));
00665         AE_TRIA(VP(0), VP(1), MP(1));
00666         AE_TRIA(VP(0), MP(2), VP(3));
00667         AE_TRIA(MP(1), VP(2), MP(2));
00668         break;              
00669     case 7:
00670         AE_QUAD(VP(1), MP(1), MP(3), VP(0));
00671         AE_TRIA(MP(1), MP(2), MP(3));
00672         AE_TRIA(MP(1), VP(2), MP(2));
00673         AE_TRIA(MP(2), VP(3), MP(3));
00674         break;              
00675     case 8:
00676         AE_TRIA(VP(2), MP(0), VP(1));
00677         AE_TRIA(VP(2), VP(3), MP(0));
00678         AE_TRIA(VP(3), VP(0), MP(0));
00679         break;              
00680     case 9:
00681         AE_TRIA(VP(2), MP(3), MP(0));
00682         AE_TRIA(VP(2), VP(3), MP(3));
00683         AE_TRIA(VP(2), MP(0), VP(1));
00684         AE_TRIA(MP(3), VP(0), MP(0));
00685         break;              
00686     case 10:
00687         AE_QUAD(VP(2), MP(2), MP(0), VP(1));
00688         AE_QUAD(MP(2), VP(3), VP(0), MP(0));
00689         break;              
00690     case 11:
00691         AE_QUAD(VP(2), MP(2), MP(0), VP(1));
00692         AE_TRIA(MP(2), MP(3), MP(0));
00693         AE_TRIA(MP(2), VP(3), MP(3));
00694         AE_TRIA(MP(3), VP(0), MP(0));
00695         break;              
00696     case 12:
00697         AE_TRIA(VP(3), MP(0), MP(1));
00698         AE_TRIA(VP(3), VP(0), MP(0));
00699         AE_TRIA(VP(3), MP(1), VP(2));
00700         AE_TRIA(MP(0), VP(1), MP(1));
00701         break;              
00702     case 13:
00703         AE_QUAD(VP(3), MP(3), MP(1), VP(2));
00704         AE_TRIA(MP(3), MP(0), MP(1));
00705         AE_TRIA(MP(3), VP(0), MP(0));
00706         AE_TRIA(MP(0), VP(1), MP(1));
00707         break;              
00708     case 14:
00709         AE_QUAD(VP(0), MP(0), MP(2), VP(3));
00710         AE_TRIA(MP(0), MP(1), MP(2));
00711         AE_TRIA(MP(0), VP(1), MP(1));
00712         AE_TRIA(MP(1), VP(2), MP(2));
00713         break;              
00714     case 15:
00715         AE_TRIA(VP(1), MP(1), MP(0));
00716         AE_TRIA(MP(0), MP(3), VP(0));
00717         AE_TRIA(MP(1), VP(2), MP(2));
00718         AE_TRIA(MP(2), VP(3), MP(3));
00719         AE_QUAD(MP(0), MP(1), MP(2), MP(3));
00720         break;              
00721     }
00722 }
00723 
00724 Void HierElem::ProjTri(Renderer &r, RenderStyle style, Int code, RadElem *mid)
00725 // Projected version of DrawTri
00726 {
00727     switch (code)   // 8 cases for a tri...
00728     {
00729     case 0:
00730         AE_TRIA(VP(0), VP(1), VP(2));
00731         break;
00732     case 1:
00733         AE_TRIA(VP(0), VP(1), MP(2));
00734         AE_TRIA(VP(1), VP(2), MP(2));
00735         break;
00736     case 2:
00737         AE_TRIA(VP(0), VP(1), MP(1));
00738         AE_TRIA(MP(1), VP(2), VP(0));
00739         break;
00740     case 3:
00741         AE_QUAD(VP(0), VP(1), MP(1), MP(2));
00742         AE_TRIA(MP(1), VP(2), MP(2));
00743         break;
00744     case 4:
00745         AE_TRIA(VP(0), MP(0), VP(2));
00746         AE_TRIA(MP(0), VP(1), VP(2));
00747         break;
00748     case 5:
00749         AE_TRIA(VP(0), MP(0), MP(2));
00750         AE_QUAD(MP(0), VP(1), VP(2), MP(2));
00751         break;              
00752     case 6:
00753         AE_QUAD(VP(0), MP(0), MP(1), VP(2));
00754         AE_TRIA(MP(0), VP(1), MP(1));
00755         break;              
00756     case 7:
00757         AE_TRIA(VP(0), MP(0), MP(2));
00758         AE_TRIA(MP(0), VP(1), MP(1));
00759         AE_TRIA(MP(2), MP(1), VP(2));
00760         AE_TRIA(MP(0), MP(1), MP(2));
00761         break;              
00762     }
00763 }
00764 
00765 #undef AE_QUAD
00766 #undef AE_TRIA
00767 
00768 // --- Control method for anchored draw ---------------------------------------
00769 
00770 
00771 Void HierElem::DrawLeaf(Renderer &r)
00772 {
00773     if (gRadControl->gouraud && gRadControl->anchor)        // Draw a T-meshed tri/quad
00774     {
00775         if (gRadControl->funcView)
00776         {
00777             r.Begin(renLineLoop).C(cWhite);
00778             SendPoints(r);
00779             r.End();
00780         }
00781         
00782 #ifdef RAD_VIS
00783         if (highlight)
00784         {
00785             if (highlight == 1)
00786                 r.C(cRed);
00787             else if (highlight == 2)
00788                 r.C(cYellow);
00789             else if (highlight == 3)
00790                 r.C(cGreen);
00791             
00792             r.Begin(renPoly);
00793             SendPoints(r);
00794             r.End();
00795             
00796             if (!gRadControl->funcView)
00797                 return;
00798         }   
00799 #endif
00800 
00801         RadElem     mid;
00802         Int         i, code = 0;
00803         RenderStyle style;
00804                 
00805         if (gRadControl->wire)
00806             style = renLineLoop;
00807         else
00808             style = renPoly;
00809 
00810         code = CalcMidCode(&mid);
00811 
00812 #ifdef RAD_VIS
00813         mid.normal = normal;
00814         mid.colour = colour;
00815 #endif      
00816         if (IsQuad())       // T-mesh a quad...
00817             if (gRadControl->funcView)
00818                 ProjQuad(r, style, code, &mid); 
00819             else
00820                 DrawQuad(r, style, code, &mid);
00821         else    // T-meshing a tri
00822             if (gRadControl->funcView)
00823                 ProjTri(r, style, code, &mid);
00824             else
00825                 DrawTri(r, style, code, &mid);
00826     }
00827     else
00828         RadElem::Draw(r);
00829 }
00830 
00831 Void HierElem::Draw(Renderer &r)
00832 {
00833     Int i;
00834 
00835     if (HasChildren() 
00836 #ifdef RAD_VIS
00837             && !highlight
00838 #endif
00839             && (!gRadControl->choke || gRadControl->choke > level))
00840         for (i = 0; i < 4; i++)
00841             child[i]->Draw(r);
00842     else
00843         DrawLeaf(r);
00844 }
00845 
00846 // --- Tree code utils --------------------------------------------------------
00847 
00848 
00849 static Void PrintCode(ostream &s, Int level, Int treeCode)
00850 {
00851     Int i;
00852     
00853     for (i = level - 1; i >= 0; i--)
00854         s << ((treeCode >> (2 * i)) & 3);
00855 }
00856 
00857 Void HierElem::PrintID(ostream &s)
00858 {
00859     s << props->id;
00860     if (level > 0)
00861          s << ":";
00862     PrintCode(s, level, treeCode);
00863 }
00864 
00865 Void HierElem::PrintSelf(ostream &s)
00866 {
00867     RadElem::Print(s);
00868 }
00869 
00870 Void HierElem::PrintRec(ostream &s)
00871 {
00872     PrintSelf(s);
00873     
00874     if (HasChildren())
00875     {
00876         s << "\n{ ";
00877         child[0]->PrintRec(s);
00878         child[1]->PrintRec(s);
00879         child[2]->PrintRec(s);
00880         child[3]->PrintRec(s);
00881         s << "}\n";
00882     }
00883 }
00884 
00885 StrConst HierElem::Name()
00886 {
00887     return("hier");
00888 }
00889 
00890 Void HierElem::Print(ostream &s)
00891 {
00892     PrintRec(s);
00893 }
00894 
00895 Void HierElem::ParseSelf(istream &s)
00896 {
00897     RadElem::Parse(s);
00898 }
00899 
00900 Void HierElem::Parse(istream &s)
00901 {
00902     Char c;
00903     Int i;
00904 
00905     ParseSelf(s);
00906 
00907     ChompWhiteSpace(s);
00908     
00909     if (s.peek() == '{')                    // children?
00910     {
00911         s.get(c);
00912         
00913         for (i = 0; i < 4; i++)
00914         {
00915             child[i] = New();
00916             child[i]->Parse(s);
00917         }     
00918         
00919         ChompWhiteSpace(s);
00920         if (s.peek() != '}')    
00921             _Warning("(HierElem::Parse) didn't find '}'");
00922         else    
00923             s.get(c);
00924     }
00925     else
00926         for (i = 0; i < 4; i++)
00927             child[i] = 0;
00928 }
00929 
00930 RadElem *HierElem::FindContainer(Coord &coord)
00931 {
00932     // Find the child the coord belongs to, and recursively descend.
00933     
00934     if (!HasChildren())
00935         return(this);
00936     else if (IsTri())
00937     {
00938         if (coord[0] + coord[1] < 0.5)  // bottom-left
00939         {
00940             coord[0] *= 2;
00941             coord[1] *= 2;
00942             return(child[1]->FindContainer(coord));
00943         }
00944         else if (coord[1] > 0.5)        // top 
00945         {
00946             coord[0] *= 2;
00947             coord[1] = 2 * coord[1] - 1;
00948             return(child[0]->FindContainer(coord));
00949         }
00950         else if (coord[0] > 0.5)        // bottom-right
00951         {
00952             coord[0] = 2 * coord[0] - 1;
00953             coord[1] *= 2;
00954             return(child[2]->FindContainer(coord));
00955         }
00956         else                            // middle
00957         {
00958             coord[0] = 1 - 2 * coord[0];
00959             coord[1] = 1 - 2 * coord[1];
00960             return(child[3]->FindContainer(coord));
00961         }
00962     }
00963     else
00964     {
00965         static Int  childMap[4] = { 1, 2, 0, 3 };
00966         Int         idx = 0;
00967 
00968         coord *= 2.0;
00969 
00970         if (coord[0] >= 1.0)
00971         {
00972             idx++;
00973             coord[0] -= 1.0;
00974         }
00975 
00976         if (coord[1] >= 1.0)
00977         {
00978             idx += 2;
00979             coord[1] -= 1.0;
00980         }
00981 
00982         // map into our weird-ass numbering scheme and return
00983         return(child[childMap[idx]]->FindContainer(coord));
00984     }
00985 }
00986 
00987 GCLReal HierElem::RadError()
00988 {
00989     Int     i;
00990     Colour  temp; 
00991     GCLReal min, max;
00992     GCLReal response;
00993             
00994     for (i = 0; i < Sides(); i++)
00995     {
00996         temp = VtxClr(i);
00997         
00998         // Now we map the colour temp to a perceptual response...
00999         
01000         // or we should: simple linear c. + clip for now.
01001         response = dot(cRGBToLum, temp);
01002         if (response > 1.0)
01003             response = 1.0;
01004 
01005         // done.
01006        
01007         if (i == 0)
01008             min = max = response;
01009         else if (response > max)
01010             max = response;
01011         else if (response < min)
01012             min = response;
01013     }
01014 
01015     return((max - min) * area * 10.0);
01016 }
01017 
01018 
01019 // --- Bilevel radiosity methods ----------------------------------------------
01020 
01021 
01022 Void HierElem::CreatePatches(PatchList &patches)
01023 {
01024     Int i;
01025 
01026     level = 0;
01027 
01028     if (area < 1 / sqr(gRadControl->patchSubdivs))
01029         patches.Append(this);
01030     else
01031     {
01032         if (!HasChildren())
01033             Subdivide();
01034         for (i = 0; i < 4; i++)
01035             child[i]->CreatePatches(patches);
01036     }
01037 }
01038 
01039 Void HierElem::CreateElements(PatchList &elements, IndexList &eltParents,
01040                               Int parent)
01041 {
01042     Int i, j;
01043             
01044     if (area < 1 / sqr(gRadControl->eltSubdivs))
01045     {
01046         elements.Append(this);
01047         eltParents.Append(parent);
01048     }
01049     else    
01050     {
01051         if (!HasChildren())
01052             Subdivide();
01053         for (i = 0; i < 4; i++)
01054             child[i]->CreateElements(elements, eltParents, parent);
01055     }
01056 }
01057 
01058 Void HierElem::SetColour(const Colour &c)
01059 {
01060     colour = c;
01061 
01062     if (HasChildren())
01063     {
01064         child[0]->SetColour(c);
01065         child[1]->SetColour(c);
01066         child[2]->SetColour(c);
01067         child[3]->SetColour(c);
01068     }
01069 }
01070 
01071 GCLReal HierElem::MemoryUse()
01072 {
01073     GCLReal result = (GCLReal) sizeof(SELF);
01074     
01075     if (HasChildren())
01076     {
01077         result += child[0]->MemoryUse();
01078         result += child[1]->MemoryUse();
01079         result += child[2]->MemoryUse();
01080         result += child[3]->MemoryUse();
01081     }
01082 
01083     return(result);
01084 }
01085 
01086 Int HierElem::CalcMidCode(RadElem *mid)
01087 {
01088     Int         i, oppDir, code, ch1o, ch2o;
01089     HierElem    **nc;
01090     
01091     code = 0;
01092     
01093     if (IsQuad())       
01094         for (i = 0; i < 4 ; i++)        // Build midpoint code
01095         {
01096             code = code << 1;
01097             if (NbFace(i) && NbFace(i)->HasChildren())
01098             {
01099                 nc = NbFace(i)->child;
01100                 oppDir = nbEdge[i];
01101                 ch1o = tQuadDirToCh1[oppDir];
01102                 ch2o = tQuadDirToCh2[oppDir];
01103                 
01104                 mid->SetIndexes(i, nc[ch1o], ch2o);
01105                 code |= 1;
01106             }
01107         }
01108     else    
01109         for (i = 0; i < 3 ; i++)        // Build midpoint code
01110         {
01111             code = code << 1;
01112             if (NbFace(i) && NbFace(i)->HasChildren())
01113             {
01114                 nc = NbFace(i)->child;
01115                 oppDir = nbEdge[i];
01116                 ch1o = tTriDirToCh1[oppDir];
01117                 ch2o = tTriDirToCh2[oppDir];
01118 
01119                 mid->SetIndexes(i, nc[ch1o], ch2o);
01120                 code |= 1;
01121             }
01122         }       
01123 
01124     mid->props = props;
01125 
01126     return(code);
01127 }
01128 
01129 #define MAKE_SUB_ELEM(E0, I0, E1, I1, E2, I2, E3, I3)                   \
01130     subElems[numElems] = New();                                         \
01131     subElems[numElems]->SetAllIndexes(E0, I0, E1, I1, E2, I2, E3, I3);  \
01132     subElems[numElems]->SetProps(props);                                \
01133     numElems++          
01134 
01135 #define AE_QUAD(A, B, C, D)     MAKE_SUB_ELEM(A, B, C, D)
01136 #define AE_TRIA(A, B, C)        MAKE_SUB_ELEM(A, B, C, &triTmpl, 3)
01137 
01138 Void HierElem::SplitElement(Int &numElems, HierElemPtr subElems[5])
01145 {
01146 
01147     RadElem     midStore, triTmpl;
01148     RadElemPtr  mid = &midStore;
01149     Int         code;
01150     
01151     code = CalcMidCode(mid);
01152     numElems = 0;  
01153     triTmpl.index[3] = -1;
01154 
01155     // Now, do the necessary triangulation...
01156     
01157     if (IsQuad())
01158         switch (code)   // 16 cases for a quad...
01159         {
01160         case 0:
01161             AE_QUAD(VP(1), VP(2), VP(3), VP(0));
01162             break;
01163         case 1:
01164             AE_TRIA(VP(1), MP(3), VP(0));
01165             AE_TRIA(VP(1), VP(2), MP(3));
01166             AE_TRIA(VP(2), VP(3), MP(3));
01167             break;
01168         case 2:
01169             AE_TRIA(VP(0), MP(2), VP(3));
01170             AE_TRIA(VP(0), VP(1), MP(2));
01171             AE_TRIA(VP(1), VP(2), MP(2));
01172             break;
01173         case 3:
01174             AE_TRIA(VP(1), MP(2), MP(3));
01175             AE_TRIA(VP(1), VP(2), MP(2));
01176             AE_TRIA(VP(1), MP(3), VP(0));
01177             AE_TRIA(MP(2), VP(3), MP(3));
01178             break;
01179         case 4:
01180             AE_TRIA(VP(3), MP(1), VP(2));
01181             AE_TRIA(VP(3), VP(0), MP(1));
01182             AE_TRIA(VP(0), VP(1), MP(1));
01183             break;
01184         case 5:
01185             AE_QUAD(VP(1), MP(1), MP(3), VP(0));
01186             AE_QUAD(MP(1), VP(2), VP(3), MP(3));
01187             break;              
01188         case 6:
01189             AE_TRIA(VP(0), MP(1), MP(2));
01190             AE_TRIA(VP(0), VP(1), MP(1));
01191             AE_TRIA(VP(0), MP(2), VP(3));
01192             AE_TRIA(MP(1), VP(2), MP(2));
01193             break;              
01194         case 7:
01195             AE_QUAD(VP(1), MP(1), MP(3), VP(0));
01196             AE_TRIA(MP(1), MP(2), MP(3));
01197             AE_TRIA(MP(1), VP(2), MP(2));
01198             AE_TRIA(MP(2), VP(3), MP(3));
01199             break;              
01200         case 8:
01201             AE_TRIA(VP(2), MP(0), VP(1));
01202             AE_TRIA(VP(2), VP(3), MP(0));
01203             AE_TRIA(VP(3), VP(0), MP(0));
01204             break;              
01205         case 9:
01206             AE_TRIA(VP(2), MP(3), MP(0));
01207             AE_TRIA(VP(2), VP(3), MP(3));
01208             AE_TRIA(VP(2), MP(0), VP(1));
01209             AE_TRIA(MP(3), VP(0), MP(0));
01210             break;              
01211         case 10:
01212             AE_QUAD(VP(2), MP(2), MP(0), VP(1));
01213             AE_QUAD(MP(2), VP(3), VP(0), MP(0));
01214             break;              
01215         case 11:
01216             AE_QUAD(VP(2), MP(2), MP(0), VP(1));
01217             AE_TRIA(MP(2), MP(3), MP(0));
01218             AE_TRIA(MP(2), VP(3), MP(3));
01219             AE_TRIA(MP(3), VP(0), MP(0));
01220             break;              
01221         case 12:
01222             AE_TRIA(VP(3), MP(0), MP(1));
01223             AE_TRIA(VP(3), VP(0), MP(0));
01224             AE_TRIA(VP(3), MP(1), VP(2));
01225             AE_TRIA(MP(0), VP(1), MP(1));
01226             break;              
01227         case 13:
01228             AE_QUAD(VP(3), MP(3), MP(1), VP(2));
01229             AE_TRIA(MP(3), MP(0), MP(1));
01230             AE_TRIA(MP(3), VP(0), MP(0));
01231             AE_TRIA(MP(0), VP(1), MP(1));
01232             break;              
01233         case 14:
01234             AE_QUAD(VP(0), MP(0), MP(2), VP(3));
01235             AE_TRIA(MP(0), MP(1), MP(2));
01236             AE_TRIA(MP(0), VP(1), MP(1));
01237             AE_TRIA(MP(1), VP(2), MP(2));
01238             break;              
01239         case 15:
01240             AE_TRIA(VP(1), MP(1), MP(0));
01241             AE_TRIA(MP(0), MP(3), VP(0));
01242             AE_TRIA(MP(1), VP(2), MP(2));
01243             AE_TRIA(MP(2), VP(3), MP(3));
01244             AE_QUAD(MP(0), MP(1), MP(2), MP(3));
01245             break;              
01246         }
01247     else
01248         switch (code)   // 8 cases for a tri...
01249         {
01250         case 0:
01251             AE_TRIA(VP(0), VP(1), VP(2));
01252             break;
01253         case 1:
01254             AE_TRIA(VP(0), VP(1), MP(2));
01255             AE_TRIA(VP(1), VP(2), MP(2));
01256             break;
01257         case 2:
01258             AE_TRIA(VP(0), VP(1), MP(1));
01259             AE_TRIA(MP(1), VP(2), VP(0));
01260             break;
01261         case 3:
01262             AE_QUAD(VP(0), VP(1), MP(1), MP(2));
01263             AE_TRIA(MP(1), VP(2), MP(2));
01264             break;
01265         case 4:
01266             AE_TRIA(VP(0), MP(0), VP(2));
01267             AE_TRIA(MP(0), VP(1), VP(2));
01268             break;
01269         case 5:
01270             AE_TRIA(VP(0), MP(0), MP(2));
01271             AE_QUAD(MP(0), VP(1), VP(2), MP(2));
01272             break;              
01273         case 6:
01274             AE_TRIA(MP(0), VP(1), MP(1));
01275             AE_QUAD(VP(0), MP(0), MP(1), VP(2));
01276             break;              
01277         case 7:
01278             AE_TRIA(VP(0), MP(0), MP(2));
01279             AE_TRIA(MP(0), VP(1), MP(1));
01280             AE_TRIA(MP(2), MP(1), VP(2));
01281             AE_TRIA(MP(0), MP(1), MP(2));
01282             break;              
01283         }
01284 }
01285 
01286 #undef MAKE_SUB_ELEM
01287 #undef AE_QUAD
01288 #undef AE_TRIA
01289 #undef VP
01290 #undef MP
01291 
01292 Void HierElem::CorrectLeaves()
01296 {
01297     if (HasChildren())
01298     {
01299         child[0]->colour = colour;
01300         child[1]->colour = colour;
01301         child[2]->colour = colour;
01302         child[3]->colour = colour;
01303         child[0]->CorrectLeaves();
01304         child[1]->CorrectLeaves();
01305         child[2]->CorrectLeaves();
01306         child[3]->CorrectLeaves();
01307     }
01308 }
01309 
01310 Void HierElem::CollectLeaves(PatchList &leaves)
01311 {
01312     if (HasChildren())
01313         for (Int i = 0; i < 4; i++)
01314             child[i]->CollectLeaves(leaves);
01315     else
01316         leaves.Append(this);
01317 }
01318 
01319 
01320 // --- Hierarchical grid methods ----------------------------------------------
01321 
01322 
01323 RadElemPtr HierGrid::AddChild(RadElem &quad, Int i, Int j, Int in, Int jn)
01324 {
01325     HierElem    newElem;
01326     
01327     // Called by ::Mesh to add a new quad to the grid.
01328     
01329     if (i == 0 && j == 0)
01330         children.PreAllocate(in * jn);
01331     
01332     (RadElem &) newElem = quad;
01333     children.Append(newElem);
01334 
01335     return(&children.Last());
01336 }
01337 
01338 Void HierGrid::ConnectChildren()
01339 //  Fill in the neighbour fields of all our children.
01340 {
01341     Int i, j;
01342     Int pos;
01343     
01344     //  Join up mesh neighbours
01345     
01346     if (IsQuad())
01347     {
01348         // traverse the rectangular grid
01349 
01350         for (i = 0; i < rows; i++)
01351             for (j = 0; j < cols; j++)
01352             {
01353                 pos = i * cols + j;
01354             
01355                 if (i > 0)  // connect with top neighbour
01356                 {
01357                     children[pos].nbFace[3] = &(children[pos - cols]);
01358                     children[pos - cols].nbFace[1] = &(children[pos]);
01359                     children[pos].nbEdge[3] = 1;
01360                     children[pos - cols].nbEdge[1] = 3;
01361                 }
01362                 if (j > 0)  // connect with left neighbour
01363                 {
01364                     children[pos].nbFace[0] = &(children[pos - 1]);
01365                     children[pos - 1].nbFace[2] = &(children[pos]);
01366                     children[pos].nbEdge[0] = 2;
01367                     children[pos - 1].nbEdge[2] = 0;
01368                 }
01369             }
01370     }
01371     else
01372     {
01373         Int orient, left, upper;
01374 
01375         pos = 0;
01376         
01377         // traverse the triangular grid
01378         
01379         /*
01380             2   1
01381            0+--+        the diagonal is dir 2 for both tris
01382             |\ |        the upper/lower side is dir 1 for both tris
01383             | \|        the left/right side is dir 0 for both tris. 
01384             +--+0       lower tri is orient = 0, upper is orient = 1.
01385            1   2
01386         */
01387 
01388         for (i = 0; i < rows; i++)
01389             for (j = 0; j < 2 * i + 1; j++)
01390             {
01391                 orient = (i + pos) & 1;     // which way is this tri oriented?
01392                         
01393                 if (i > 0 && orient)        // connect with top neighbour
01394                 {
01395                     upper = pos - 2 * i;    // index of upper neighbour
01396                     children[pos].nbFace[1] = &(children[upper]);
01397                     children[upper].nbFace[1] = &(children[pos]);
01398                     children[pos].nbEdge[1] = 1;
01399                     children[upper].nbEdge[1] = 1;
01400                 }
01401                 if (j > 0 || orient)        // connect with left/diag. neighbour
01402                 {
01403                     left = pos - 1;         // index of left neighbour
01404                     orient = orient << 1;   // direction 1 or 2?
01405                     children[pos].nbFace[orient] = &(children[left]);
01406                     children[left].nbFace[orient] = &(children[pos]);
01407                     children[pos].nbEdge[orient] = orient;
01408                     children[left].nbEdge[orient] = orient;
01409                 }
01410                 pos++;
01411             }
01412     }
01413 }
01414 
01415 Void HierGrid::Draw(Renderer &r)
01416 {
01417     if (children.NumItems() > 0 
01418 #ifdef RAD_VIS
01419         && !highlight
01420 #endif
01421         )
01422     {
01423         Int i;
01424         
01425         for (i = 0; i < children.NumItems(); i++)
01426             children[i].Draw(r);
01427     }
01428     else
01429         RadElem::Draw(r);
01430 }
01431 
01432 Void HierGrid::CreatePatches(PatchList &patches)
01433 {
01434     Int i;
01435     
01436     if (gRadControl->patchSubdivs == 0.0)
01437     {
01438         gRadControl->patchSubdivs = 1e-32;
01439         gRadControl->eltSubdivs = 1e-32;
01440     }
01441         
01442     children.Clear();
01443 
01444     Mesh(gRadControl->patchSubdivs);    
01445     ConnectChildren();
01446     
01447     for (i = 0; i < children.NumItems(); i++)
01448         patches.Append(&(children[i]));
01449 }
01450 
01451 RadElem *HierGrid::FindContainer(Coord &coord)
01452 {
01453     Int i = FindChildIndex(coord);
01454     
01455     return(children[i].FindContainer(coord));
01456 }
01457 
01458 Void HierGrid::ColourVertices(Int weights[])
01459 {
01460     Int i;
01461     
01462     for (i = 0; i < children.NumItems(); i++)
01463         children[i].ColourVertices(weights);
01464 }
01465 
01466 StrConst HierGrid::Name()
01467 {
01468     return("hgrid");
01469 }
01470 
01471 Void HierGrid::Print(ostream &s)
01472 {
01473     RadElem::Print(s);
01474     s << rows << ' ' << cols << ' ' << children << ' ';
01475 }
01476 
01477 Void HierGrid::Parse(istream &s)
01478 {
01479     Int i;
01480     Char c;
01481 
01482     RadElem::Parse(s);  
01483     s >> rows >> cols;
01484 
01485     children.SetSize(rows * cols);
01486 
01487     ChompWhiteSpace(s); // swallow bracket
01488     s.get(c);
01489     for (i = 0; i < children.NumItems(); i++)
01490         children[i].Parse(s);
01491     ChompWhiteSpace(s);
01492     s.get(c);
01493 
01494     ConnectChildren();
01495 
01496     for (i = 0; i < children.NumItems(); i++)
01497         children[i].props = props;
01498 }
01499 
01500 Void HierGrid::Reanimate(RadElem *parent)
01501 {
01502     Int i;
01503 
01504     if (parent)
01505         SetProps(parent->props);
01506 
01507     for (i = 0; i < children.NumItems(); i++)
01508         children[i].Reanimate(this);
01509 }
01510 
01511 GCLReal HierGrid::MemoryUse()
01512 {
01513     Int     i;
01514     GCLReal result;
01515 
01516     result = sizeof(SELF);
01517     sGridMem += (Int) result;
01518     sGridChildMem += children.NumItems() * sizeof(HierElem);    
01519 
01520     for (i = 0; i < children.NumItems(); i++)
01521         result += children[i].MemoryUse();
01522 
01523     return(result);
01524 }

Generated at Sat Aug 5 00:26:51 2000 for Radiator by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000