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 }