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

AltStyle によって変換されたページ (->オリジナル) /