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

MRModel.cc

Go to the documentation of this file.
00001 /*
00002 File: MRModel.cc
00003 
00004 Function: Implements a multiresolution polygonal model
00005 
00006 Author: Andrew Willmott
00007 
00008 Notes: 
00009 */
00010 
00011 #include "gcl/MRModel.h"
00012 #include "cl/String.h"
00013 #include "gcl/VecUtil.h"
00014 #include "gcl/Draw.h"
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <errno.h>
00018 
00019 #ifdef DEBUG
00020 #define MRV_COUT if (true) cerr
00021 #else
00022  #define MRV_COUT if (false) cerr
00023 #endif
00024 
00025  #define MR_MEM_MAP
00026 
00027 #ifdef MR_MEM_MAP
00028 #include <unistd.h>
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #include <fcntl.h>
00032 #include <sys/mman.h>
00033 #endif
00034 
00035 #include <new.h>
00036 
00037 
00058  const Int kMRBVersion = 3;
00059 
00060 
00061  MRModel::MRModel() :
00062 lastComplexity(1.0),
00063 showMeta(false),
00064 showFaces(true),
00065 colourFaces(false),
00066 currentFaces(0),
00067 currentClusters(0),
00068 clustersPrepped(false),
00069 verticesPrepped(false)
00070 {
00071 colour = scPrimitive::sDefaultColour;
00072 points = 0;
00073 colours = 0;
00074 }
00075 
00076  MRModel::~MRModel()
00077 {
00078 }
00079 
00080 Bool MRModel::sAvgClusColours = false;
00081 
00082  Void MRModel::AddContraction(
00083 Int child0, 
00084 Int child1,
00085 Int face0,
00086 Int face1,
00087 GCLReal error,
00088 const Point &p,
00089 Int delta
00090 )
00092 {
00093 MRVertex newVtx;
00094 
00095 if (vertices.NumItems() == 0)
00096 // if this is first contraction, set up all the data structures we'll
00097 // need
00098 {
00099 Int i;
00100 
00101 vertices.SetSize(points->NumItems());
00102 vertices.ClearTo(newVtx);
00103 vtxFlags.SetSize(points->NumItems() * 2 - 1);
00104 vtxFlags.ClearTo(Flags8());
00105 
00106 // make the leaf vertices active
00107 for (i = 0; i < vertices.NumItems(); i++)
00108 vtxFlags[i].Set(MRV_Active);
00109 
00110 for (i = 0; i < faces.NumItems(); i++)
00111 vtxFlags[i].Set(MRV_FaceActive);
00112 }
00113 
00114 points->Append(p);
00115 
00116 if (delta)
00117 points->Last() += points->Item(child0);
00118 
00119 // MMF format uses an in-place numbering scheme (a contracted
00120 // vertex replaces its left child in a vertex array) so we
00121 // must walk up to the roots of the indicated vertices to
00122 // find the vertex that's really being referred to.
00123 
00124 while (!vertices[child0].IsRoot())
00125 child0 = vertices[child0].parent;
00126 while (!vertices[child1].IsRoot())
00127 child1 = vertices[child1].parent;
00128 
00129 // Set the contraction!
00130 newVtx.SetContraction(vertices, vertices.NumItems(), vtxFlags,
00131 child0, child1, face0, face1, error);
00132 vertices.Append(newVtx);
00133 
00134 Assert(vtxFlags[vertices.NumItems() - 1].IsSet(MRV_Inside), "flag not set");
00135 
00136 Assert(vertices.NumItems() == points->NumItems(), "point/vertex mismatch");
00137 }
00138 
00139  Void MRModel::AddCluster(
00140 Int clusLeft,
00141 Int clusRight,
00142 Point &clusOrig,
00143 VecTrans &clusAxis,
00144 Vector &clusFitNormal,
00145 GCLReal clusD,
00146 Point &clusMin,
00147 Point &clusMax,
00148 Int clusID
00149 )
00151 {
00152 Point obbOrig;
00153 Vector scales;
00154 Int i;
00155 
00156 clusLeft--;
00157 clusRight--;
00158 
00159 if (clusters.NumItems() == 0)
00160 {
00161 MRV_COUT << "adding first cluster: preallocating space for " << 
00162 faces.NumItems() - 1 << " clusters" << endl;
00163 
00164 clusters.SetSize(faces.NumItems() - 1);
00165 firstClusterID = 2 * faces.NumItems() - 2;
00166 lastClusterID = faces.NumItems();
00167 clustersActive.SetSize(faces.NumItems() * 2 - 1);
00168 for (i = 0; i < faces.NumItems(); i++)
00169 clustersActive[i] = 1;
00170 
00171 MRV_COUT << "done." << endl;
00172 }
00173 
00174 Assert(clusLeft < clustersActive.NumItems() && clusRight < clustersActive.NumItems(),
00175 "Clusters not in tree order in cmf file.");
00176 
00177 FaceCluster &newCluster = Cluster(clusID);
00178 
00179 if (clusID & 8191 == 0)
00180 MRV_COUT << "adding cluster " << clusID << endl;
00181 
00182 newCluster.child[0] = clusLeft;
00183 newCluster.child[1] = clusRight;
00184 
00185 // convert to our storage format.
00186 
00187 // Garland's OBB axes are not unit length, and may not be right
00188 // handed. (The smallest evec may have been flipped to point in the
00189 // same direction as the sum-area normal).
00190 
00191 scales[0] = len(clusAxis[0]);
00192 scales[1] = len(clusAxis[1]);
00193 scales[2] = len(clusAxis[2]);
00194 // correct if left-handed
00195 if (det(clusAxis) < 0)
00196 {
00197 // flip y axis to correct, 'cause we want to keep z pointing same way
00198 // as normal
00199 scales[1] = -scales[1];
00200 Swap(clusMin[1], clusMax[1]);
00201 }
00202 clusAxis[0] /= scales[0];
00203 clusAxis[1] /= scales[1];
00204 clusAxis[2] /= scales[2];
00205 clusMin *= scales;
00206 clusMax *= scales;
00207 newCluster.SetAxes(clusAxis);
00208 
00209 // transform origin into bbox coords
00210 obbOrig = clusAxis * clusOrig;
00211 clusMin += obbOrig;
00212 clusMax += obbOrig;
00213 
00214 newCluster.min = clusMin;
00215 newCluster.max = clusMax;
00216 
00217 for (i = 0; i < 6; i++)
00218 newCluster.sideArea[i] = 255;
00219 
00220 Assert(clusMin[0] <= clusMax[0], "bad x bb");
00221 Assert(clusMin[1] <= clusMax[1], "bad y bb");
00222 Assert(clusMin[2] <= clusMax[2], "bad z bb");
00223 
00224 clustersActive[clusID] = 1;
00225 
00226 if (clusLeft >= 0)
00227 {
00228 Assert(clustersActive[clusLeft], "left child not clusterable");
00229 clustersActive[clusLeft] = 0;
00230 }
00231 if (clusRight >= 0)
00232 {
00233 Assert(clustersActive[clusRight], "right child not clusterable");
00234 clustersActive[clusRight] = 0;
00235 }
00236 }
00237 
00238  static GCLReal ProjectedLength(const Point &p1, const Point &p2,
00239 const Transform &projMat)
00241 {
00242 HPoint hp1(p1, 1.0), hp2(p2, 1.0);
00243 Vector c1, c2;
00244 Coord result;
00245 
00246 c1[0] = dot(projMat[0], hp1);
00247 c1[1] = dot(projMat[1], hp1);
00248 c1[2] = dot(projMat[3], hp1);
00249 
00250 c2[0] = dot(projMat[0], hp2);
00251 c2[1] = dot(projMat[1], hp2);
00252 c2[2] = dot(projMat[3], hp2);
00253 
00254 result = proj(c1) - proj(c2);
00255 
00256 return(sqrlen(result));
00257 }
00258 
00259 
00260  Void MRModel::AdaptLength(
00261 GCLReal threshold,
00262 const Transform &M,
00263 const Transform &P,
00264 Float timeLimit
00265 )
00270 {
00271 Transform PM = xform(P, M);
00272 Int i;
00273 
00274 // Square the threshold so we can avoid all those sqrt's
00275 threshold = sqr(threshold);
00276 
00277 // iterate over active vertices -- brute force for now...
00278 for (i = 0; i < vertices.NumItems(); i++)
00279 if (vtxFlags[i].IsSet(MRV_Active))
00280 {
00281 Bool canExpand = false;
00282 Bool canContract = false;
00283 MRVertex &v = vertices[i];
00284 
00285 if (v.CanExpand(i, vtxFlags))
00286 {
00287 if (threshold < ProjectedLength(points->Item(i), 
00288 points->Item(v.child[0]), PM))
00289 canExpand = true;
00290 else if (threshold < ProjectedLength(points->Item(i), 
00291 points->Item(v.child[1]), PM))
00292 canExpand = true;
00293 }
00294 
00295 if (!v.IsRoot() && vertices[v.parent].CanContract(v.parent, vtxFlags))
00296 {
00297 MRVertex &vp = vertices[v.parent];
00298 
00299 if (threshold > ProjectedLength(points->Item(v.parent), 
00300 points->Item(vp.child[0]), PM))
00301 canContract = true;
00302 else if (threshold > ProjectedLength(points->Item(v.parent), 
00303 points->Item(vp.child[1]), PM))
00304 canContract = true;
00305 }
00306 
00307 if (canExpand)
00308 v.Expand(i, vtxFlags);
00309 else if (canContract)
00310 vertices[v.parent].Contract(v.parent, vtxFlags);
00311 
00312 if (canExpand && canContract)
00313 MRV_COUT << "YOW! Tricky situation." << endl;
00314 }
00315 
00316 AdjustLeafFaces();
00317 }
00318 
00319  Void MRModel::AdaptFaces(Int targetFaces)
00320 {
00321 Int i;
00322 
00323 MRV_COUT << "Adapting to " << targetFaces << endl;
00324 
00325 if (targetFaces > currentFaces)
00326 {
00327 // Search for expansions until we have enough faces
00328 
00329 MRV_COUT << "Expanding: " << flush;
00330 
00331 for (i = vertices.NumItems() - 1; targetFaces > currentFaces && i >= 0; i--)
00332 {
00333 MRVertex &v = vertices[i];
00334 
00335 if (v.CanExpand(i, vtxFlags))
00336 {
00337 v.Expand(i, vtxFlags);
00338 if (v.face[0] >= 0)
00339 currentFaces++;
00340 if (v.face[1] >= 0)
00341 currentFaces++;
00342 }
00343 }
00344 }
00345 else if (targetFaces < currentFaces)
00346 {
00347 // Search for contractions
00348 
00349 MRV_COUT << "Contracting: " << flush;
00350 
00351 for (i = 0; (targetFaces < currentFaces) && i < vertices.NumItems(); i++)
00352 {
00353 MRVertex &v = vertices[i];
00354 
00355 if (v.CanContract(i, vtxFlags))
00356 {
00357 v.Contract(i, vtxFlags);
00358 if (v.face[0] >= 0)
00359 currentFaces--;
00360 if (v.face[1] >= 0)
00361 currentFaces--;
00362 }
00363 }
00364 }
00365 
00366 AdjustLeafFaces();
00367 
00368 MRV_COUT << "Model faces: " << currentFaces << endl;
00369 }
00370 
00371  Void MRModel::AdaptClusters(Int targetClusters)
00372 {
00373 Int i;
00374 
00375 MRV_COUT << "Adapting to " << targetClusters << endl;
00376 
00377 if (clustersActive.NumItems() == 0)
00378 // don't have an active cluster list, so better create one now.
00379 {
00380 MRV_COUT << "Creating active list" << endl;
00381 currentClusters = rootClusters.NumItems();
00382 clustersActive.SetSize(faces.NumItems() * 2 - 1);
00383 clustersActive.ClearTo(0);
00384 
00385 // firstActiveClus = clustersActive.NumItems();
00386 for (i = 0; i < rootClusters.NumItems(); i++)
00387 {
00388 // firstActiveClus = Min(rootClusters[i], firstClusActive);
00389 clustersActive[rootClusters[i]] = 1;
00390 }
00391 }
00392 
00393 if (targetClusters > currentClusters)
00394 {
00395 Int lastExp = 0;
00396 
00397 if (flags.IsSet(MRM_Ordered))
00398 lastExp = lastClusterID;
00399 
00400 // Search for expansions until we have enough faces
00401 
00402 MRV_COUT << "Expanding: " << flush;
00403 
00404 // move through from end of log, expanding active faces
00405 for (i = clustersActive.NumItems() - 1; (targetClusters > currentClusters) 
00406 && i >= lastExp; i--)
00407 if (clustersActive[i] && !IsFace(i))
00408 {
00409 // firstClusActive = i;
00410 clustersActive[i] = 0;
00411 clustersActive[Cluster(i).child[0]] = 1;
00412 clustersActive[Cluster(i).child[1]] = 1;
00413 currentClusters++;
00414 }
00415 }
00416 else if (Max(rootClusters.NumItems(), targetClusters) < currentClusters)
00417 {
00418 // Search for contractions
00419 
00420 MRV_COUT << "Contracting: " << flush;
00421 
00422 // move through from start of log, contracting active faces
00423 for (i = lastClusterID; (targetClusters < currentClusters) 
00424 && i <= firstClusterID; i++)
00425 {
00426 Int left = Cluster(i).child[0];
00427 Int right = Cluster(i).child[1];
00428 
00429 if (clustersActive[left])
00430 {
00431 // firstClusActive = i;
00432 clustersActive[i] = 1;
00433 clustersActive[left] = 0;
00434 clustersActive[right] = 0;
00435 currentClusters--;
00436 }
00437 }
00438 }
00439 
00440 MRV_COUT << "model clusters: " << currentClusters << endl;
00441 }
00442 
00443  Void MRModel::AdaptComplexity(GCLReal complexity)
00449 {
00450 if (complexity != lastComplexity)
00451 {
00452 if (vertices.NumItems() > 0)
00453 AdaptFaces(sqr(complexity) * faces.NumItems());
00454 if (clusters.NumItems() > 0)
00455 AdaptClusters(sqr(complexity) * faces.NumItems());
00456 lastComplexity = complexity;
00457 } 
00458 }
00459 
00460  Void MRModel::AdjustLeafFaces()
00466 { 
00467 if (vertices.NumItems() == 0)
00468 currentFaces = faces.NumItems();
00469 else
00470 {
00471 Int i, numActiveFaces = 0;
00472 
00473 for (i = 0; i < vtxFaces.NumItems(); i++)
00474 if (vtxFlags[i].IsSet(MRV_FaceActive))
00475 {
00476 vtxCodes[i].AdjustVertices(vertices, vtxFlags, vtxFaces[i].v, faces[i].v);
00477 numActiveFaces++;
00478 }
00479 
00480 currentFaces = numActiveFaces;
00481 }
00482 }
00483 
00484  Void MRModel::DumpFCH(StrConst filename)
00486 {
00487 Int i, group = 0, lastActive;
00488 ofstream s;
00489 IndexList stack;
00490 
00491 s.open(filename);
00492 
00493 for (i = 0; i < clustersActive.NumItems(); i++)
00494 {
00495 if (clustersActive[i] != group)
00496 {
00497 group = clustersActive[i];
00498 s << "g " << group << endl;
00499 }
00500 s << "e " << i;
00501 if (!IsFace(i))
00502 s << ' ' << Cluster(i).child[0] << ' ' << Cluster(i).child[1];
00503 s << endl;
00504 }
00505 
00506 lastActive = -1;
00507 stack.Clear();
00508 
00509 for (i = 0; i < rootClusters.NumItems(); i++)
00510 stack.Push(rootClusters[i]);
00511 
00512 while (stack.NumItems() != 0)
00513 {
00514 i = stack.Last();
00515 stack.Pop();
00516 if (clustersActive[i])
00517 {
00518 if (lastActive >= 0)
00519 s << "l " << lastActive << ' ' << i << endl;
00520 lastActive = i;
00521 }
00522 else if (!IsFace(i))
00523 {
00524 stack.Push(Cluster(i).child[1]);
00525 stack.Push(Cluster(i).child[0]);
00526 }
00527 }
00528 
00529 s.close();
00530 }
00531 
00532  Void MRModel::CropClusters(Int numClusters)
00533 {
00534 Int i, cropClusterID;
00535 FaceIdxArray newFaces;
00536 
00537 newFaces.PreAllocate(faces.NumItems());
00538 
00539 numClusters = Clip(numClusters, 1, clusters.NumItems());
00540 
00541 cout << "clipping to " << numClusters << " clusters" << endl;
00542 
00543 // renumber leaves so that a cluster's leaves are numbered
00544 // consecutively
00545 
00546 for (i = 0; i < rootClusters.NumItems(); i++)
00547 ReorderLeafClusters(rootClusters[i], newFaces);
00548 
00549 faces.SwapWith(newFaces);
00550 flags.Set(MRM_Ordered);
00551 
00552 cropClusterID = firstClusterID - numClusters;
00553 
00554 // replace any child IDs that refer to soon-to-be discarded
00555 // clusters with appropriate face IDs.
00556 for (i = clusters.NumItems() - 1; i >= 0; i--)
00557 {
00558 if (!IsFace(clusters[i].child[0])
00559 && clusters[i].child[0] < cropClusterID)
00560 clusters[i].child[0] = Cluster(clusters[i].child[0]).child[0];
00561 
00562 if (!IsFace(clusters[i].child[1])
00563 && clusters[i].child[1] < cropClusterID)
00564 clusters[i].child[1] = Cluster(clusters[i].child[1]).child[1];
00565 }
00566 
00567 clusters.SetSize(numClusters);
00568 lastClusterID = firstClusterID - numClusters + 1;
00569 
00570 cout << "clusters from " << firstClusterID << " to " << lastClusterID << endl;
00571 
00572 if (clustersActive.NumItems() > 0)
00573 {
00574 clustersActive.ClearTo(0);
00575 
00576 for (i = 0; i < rootClusters.NumItems(); i++)
00577 clustersActive[rootClusters[i]] = 1;
00578 currentClusters = rootClusters.NumItems();
00579 }
00580 }
00581 
00582  Int MRModel::ReorderLeafClusters(Int ic, FaceIdxArray &newFaces)
00593 {
00594 if (IsFace(ic))
00595 {
00596 Int newID = newFaces.NumItems();
00597 
00598 newFaces.Append(faces[ic]);
00599 
00600 return(newID);
00601 }
00602 else
00603 {
00604 FaceCluster &clus = Cluster(ic);
00605 
00606 clus.child[0] = ReorderLeafClusters(clus.child[0], newFaces);
00607 clus.child[1] = ReorderLeafClusters(clus.child[1], newFaces);
00608 
00609 return(ic);
00610 }
00611 }
00612 
00613  Void MRModel::PrepareClusters()
00614 {
00615 Int i, j;
00616 Vector areaNormal;
00617 
00618 if (clustersPrepped)
00619 return;
00620 
00621 rootClusters.Clear();
00622 
00623 for (i = 0; i < clustersActive.NumItems(); i++)
00624 if (clustersActive[i])
00625 rootClusters.Append(i);
00626 
00627 // accumulate area normals up from leaves
00628 for (i = lastClusterID; i <= firstClusterID; i++)
00629 {
00630 FaceCluster &fc = Cluster(i);
00631 
00632 fc.areaNormal = vl_0;
00633 fc.totArea = 0;
00634 
00635 for (j = 0; j < 2; j++)
00636 if (IsFace(fc.child[j]))
00637 {
00638 areaNormal = FaceAreaNormal(fc.child[j]);
00639 fc.areaNormal += areaNormal;
00640 fc.totArea += len(areaNormal);
00641 }
00642 else
00643 {
00644 fc.areaNormal += Cluster(fc.child[j]).areaNormal;
00645 fc.totArea += Cluster(fc.child[j]).totArea;
00646 }
00647 }
00648 
00649 currentClusters = rootClusters.NumItems();
00650 
00651 MRV_COUT << "there are " << rootClusters.NumItems()
00652 << " root clusters, total clusters = " 
00653 << clustersActive.NumItems() << ", original faces = " << faces.NumItems() << endl;
00654 
00655 clustersPrepped = true;
00656 }
00657 
00658  Void MRModel::PrepareVertices()
00659 {
00660 GCLVec weights(vertices.NumItems(), vl_0);
00661 Int i, j, k;
00662 Int maxHeight, minHeight, height;
00663 TreeCodes treeCodes(vertices.NumItems());
00664 VectorList faceANs(faces.NumItems());
00665 
00666 if (verticesPrepped)
00667 return;
00668 
00669 maxHeight = 0;
00670 minHeight = 32767;
00671 rootVertices.Clear();
00672 
00673 // find all root vertices, and set up the hierarchies
00674 // corresponding to each one.
00675 for (i = 0; i < vertices.NumItems(); i++)
00676 if (vertices[i].IsRoot())
00677 {
00678 height = 0;
00679 MRSetupHierarchy(vertices, i, treeCodes, height, 0, 0);
00680 maxHeight = Max(height, maxHeight);
00681 minHeight = Min(height, minHeight);
00682 rootVertices.Append(i);
00683 } 
00684 
00685 MRV_COUT << rootVertices.NumItems() << " root vertices" << endl;
00686 
00687 for (i = 0; i < vertices.NumItems(); i++)
00688 vertices[i].areaNormal = vl_0;
00689 
00690 // Set up face info (area, normal, etc.)
00691 vtxCodes.SetSize(faces.NumItems()); 
00692 vtxFaces = faces;
00693 
00694 for (i = 0; i < vtxFaces.NumItems(); i++)
00695 {
00696 faceANs[i] = FaceAreaNormal(i);
00697 
00698 for (j = 0; j < 3; j++)
00699 {
00700 Assert(vertices[faces[i].v[j]].IsLeaf(), "Not at leaf vertices.");
00701 
00702 vtxCodes[i].treeCode[j] = treeCodes[faces[i].v[j]];
00703 vertices[faces[i].v[j]].areaNormal += faceANs[i];
00704 weights[faces[i].v[j]] += 1.0;
00705 }
00706 }
00707 
00708 // calculate vertex normals & equiv. areas. for leaf vertices
00709 for (i = 0; i < vertices.NumItems(); i++)
00710 if (weights[i] > 0.0)
00711 {
00712 GCLReal w = weights[i];
00713 
00714 vertices[i].areaNormal /= w;
00715 }
00716 
00717 // calculate aggregate properties for non-leaf vertices.
00718 for (i = 0; i < rootVertices.NumItems(); i++)
00719 vertices[rootVertices[i]].PullProps(vertices);
00720 
00721 MRV_COUT << "there are " << rootVertices.NumItems()
00722 << " root vertices, min/max vertex tree height = " 
00723 << minHeight << '/' << maxHeight
00724 << ", original vertices = " << points->NumItems() << endl;
00725 
00726 SimplestModel();
00727 
00728 verticesPrepped = true;
00729 }
00730 
00731  Void MRModel::PrepareModel()
00732 {
00733 MRV_COUT << "processing MR model" << endl;
00734 
00735 if (clusters.NumItems() > 0) 
00736 PrepareClusters();
00737 if (vertices.NumItems() > 0)
00738 PrepareVertices();
00739 
00740 MRV_COUT << "done" << endl;
00741 }
00742 
00743 #ifdef MR_MEM_MAP
00744 
00745 // XXX shift to CL
00746  Byte *MemMap(StrConst filename, Int &size)
00747 {
00748 Int fd, mapPerm;
00749 Byte *result = 0;
00750 
00751 fd = open(filename, O_RDWR);
00752 if (fd == -1)
00753 {
00754 mapPerm = PROT_READ;
00755 fd = open(filename, O_RDONLY);
00756 }
00757 else
00758 mapPerm = PROT_READ | PROT_WRITE;
00759 
00760 if (fd != -1)
00761 {
00762 Int fsize;
00763 struct stat fstats;
00764 
00765 fstat(fd, &fstats);
00766 fsize = fstats.st_size;
00767 
00768 result = (Byte*) mmap(0, fsize, mapPerm, MAP_SHARED, fd, 0);
00769 
00770 size = fsize;
00771 
00772 if (result == MAP_FAILED)
00773 {
00774 perror("mmap");
00775 _Error("MemMap failed");
00776 }
00777 close(fd);
00778 }
00779 else
00780 perror("open");
00781 
00782 return(result);
00783 }
00784 
00785  Void ReadArray(NBaseArray &a, Byte* &p, Int &size)
00786 {
00787 Int elts, chunk;
00788 
00789 elts = *((Int*) p);
00790 p += sizeof(Int);
00791 
00792 a.Attach(p, elts, true);
00793 chunk = a.EltSize() * elts;
00794 p += chunk;
00795 size -= chunk;
00796 
00797 Assert(size >= 0, "End of mapped memory chunk");
00798 }
00799 
00800  template <class T> Void ReadArray(Array<T> &a, Byte* &p, Int &size)
00801 {
00802 Int elts, chunk;
00803 
00804 elts = *((Int*) p);
00805 p += sizeof(Int);
00806 
00807 a.Attach((T*) p, elts, true);
00808 chunk = sizeof(T) * elts;
00809 p += chunk;
00810 size -= chunk;
00811 
00812 Assert(size >= 0, "End of mapped memory chunk");
00813 }
00814 
00815 #ifdef CL_SGI_INST
00816 #pragma instantiate Void ReadArray(Array<Int> &a, Byte* &p, Int &size)
00817 #endif
00818 #endif
00819 
00820  Bool MRModel::ParseBinary()
00821 {
00822 Bool result = false;
00823 Int i, j;
00824 FileName binaryFile(modelFile);
00825 
00826 binaryFile.SetPath(modelFile.GetPath());
00827 binaryFile.SetExtension("mrb");
00828 MRV_COUT << "checking for " << binaryFile.GetPath() << endl;
00829 
00830 if (modelFile.IsReadable())
00831 do
00832 {
00833 MRV_COUT << "FOUND BINARY MRB" << endl;
00834 
00835 #ifdef MR_MEM_MAP
00836 Byte *p;
00837 MRB_Header *header;
00838 Int size = 0;
00839 
00840 MRV_COUT << "memmapping cluster file" << endl;
00841 p = MemMap(modelFile.GetPath(), size);
00842 
00843 MRV_COUT << "memmapped " << size << " bytes" << endl;
00844 header = (MRB_Header*) p; 
00845 p += sizeof(MRB_Header);
00846 size -= sizeof(MRB_Header);
00847 Assert(size >= 0, "End of mapped memory chunk");
00848 if (header->version > kMRBVersion)
00849 {
00850 _Warning("Newer version");
00851 }
00852 else if (header->version < kMRBVersion)
00853 {
00854 _Warning("Older version");
00855 }
00856 
00857 MRV_COUT << "version " << header->version 
00858 << ", flags " << header->flags << endl;
00859 
00860 ReadArray(*points, p, size);
00861 MRV_COUT << points->NumItems() << " points" << endl;
00862 
00863 ReadArray(faces, p, size);
00864 MRV_COUT << faces.NumItems() << " faces" << endl;
00865 
00866 if (header->flags.IsSet(MRB_HasVH))
00867 {
00868 ReadArray(rootVertices, p, size);
00869 MRV_COUT << rootVertices.NumItems() << " root vertices" << endl;
00870 ReadArray(vertices, p, size);
00871 MRV_COUT << vertices.NumItems() << " vertices" << endl;
00872 ReadArray(vtxCodes, p, size);
00873 MRV_COUT << vtxCodes.NumItems() << " codes" << endl;
00874 }
00875 
00876 if (header->flags.IsSet(MRB_HasFH))
00877 {
00878 ReadArray(rootClusters, p, size);
00879 MRV_COUT << rootClusters.NumItems() << " root clusters" << endl;
00880 ReadArray(clusters, p, size);
00881 MRV_COUT << clusters.NumItems() << " clusters" << endl;
00882 }
00883 
00884 result = true;
00885 flags.Set(MRM_MemMapped);
00886 if (header->flags.IsSet(MRB_Ordered))
00887 flags.Set(MRM_Ordered);
00888 #else
00889 FILE *file;
00890 MRB_Header header;
00891 
00892 file = binaryFile.FOpen("r+b");
00893 if (!file)
00894 {
00895 _Warning("Couldn't open file");
00896 break;
00897 }
00898 
00899 do {
00900 if (sizeof(MRB_Header) != fread(&header, 1, sizeof(MRB_Header), file))
00901 {
00902 _Warning("couldn't read header");
00903 break;
00904 }
00905 
00906 if (header.version > kMRBVersion)
00907 {
00908 _Warning("Newer version");
00909 }
00910 else if (header.version < kMRBVersion)
00911 {
00912 _Warning("Older version");
00913 }
00914 
00915 MRV_COUT << "version " << header.version 
00916 << ", flags " << header.flags << endl;
00917 
00918 if (points->FRead(file)) break;
00919 MRV_COUT << points->NumItems() << " points" << endl;
00920 
00921 if (faces.FRead(file)) break;
00922 MRV_COUT << faces.NumItems() << " faces" << endl;
00923 
00924 if (header.flags.IsSet(MRB_HasVH))
00925 {
00926 if (rootVertices.FRead(file)) break;
00927 MRV_COUT << rootVertices.NumItems() << " root vertices" << endl;
00928 if (vertices.FRead(file)) break;
00929 MRV_COUT << vertices.NumItems() << " vertices" << endl;
00930 if (vtxCodes.FRead(file)) break;
00931 MRV_COUT << vtxCodes.NumItems() << " codes" << endl;
00932 }
00933 if (header.flags.IsSet(MRB_HasFH))
00934 {
00935 if (rootClusters.FRead(file)) break;
00936 MRV_COUT << rootClusters.NumItems() << " root clusters" << endl;
00937 if (clusters.FRead(file)) break;
00938 MRV_COUT << clusters.NumItems() << " clusters" << endl;
00939 }
00940 
00941 if (header.flags.IsSet(MRB_Ordered))
00942 flags.Set(MRB_Ordered);
00943 
00944 result = true;
00945 } while (false);
00946 
00947 if (ferror(file))
00948 {
00949 perror("error reading MRB file");
00950 break;
00951 }
00952 #endif
00953 
00954 if (vertices.NumItems() > 0)
00955 {
00956 Flags8 fa;
00957 fa.Set(MRV_FaceActive | MRV_Inside);
00958 
00959 MRV_COUT << "starting contraction prep" << endl;
00960 vtxFaces = faces;
00961 vtxFlags.SetSize(Max(vertices.NumItems(), faces.NumItems()));
00962 vtxFlags.ClearTo(fa);
00963 for (i = 0; i < faces.NumItems(); i++)
00964 for (j = 0; j < 3; j++)
00965 {
00966 vtxFlags[faces[i].v[j]].Set(MRV_Active);
00967 vtxFlags[faces[i].v[j]].UnSet(MRV_Inside);
00968 }
00969 AdjustLeafFaces(); // XXX store ms indexes to avoid?
00970 verticesPrepped = true;
00971 MRV_COUT << "done" << endl;
00972 }
00973 
00974 if (clusters.NumItems() > 0)
00975 {
00976 firstClusterID = 2 * faces.NumItems() - 2;
00977 lastClusterID = firstClusterID - clusters.NumItems() + 1;
00978 clustersPrepped = true;
00979 }
00980 }
00981 while (false);
00982 
00983 return(result);
00984 }
00985 
00986  Void MRModel::WriteBinary()
00987 {
00988 FileName binaryFile;
00989 
00990 if (flags.IsSet(MRM_MemMapped) || (clusters.NumItems() == 0 && vertices.NumItems() == 0))
00991 return;
00992 
00993 binaryFile.SetDir(".");
00994 binaryFile.SetFile(modelFile.GetFile());
00995 binaryFile.SetExtension("mrb");
00996 
00997 cerr << "Writing binary to " << binaryFile.GetPath() << endl;
00998 
00999 do
01000 {
01001 FILE *file;
01002 MRB_Header header;
01003 
01004 // XXX needs error proofed
01005 
01006 header.version = kMRBVersion;
01007 if (vertices.NumItems() > 0)
01008 header.flags.Set(MRB_HasVH);
01009 if (clusters.NumItems() > 0)
01010 header.flags.Set(MRB_HasFH);
01011 if (flags.IsSet(MRM_Ordered))
01012 header.flags.Set(MRB_Ordered);
01013 
01014 #ifdef GCL_FLOAT
01015 head.flags.Set(MRB_Float);
01016 #endif
01017 
01018 if (!points)
01019 _Error("Model has no points?");
01020 
01021 MRV_COUT << "WRITING BINARY MRB FILE" << endl;
01022 file = binaryFile.FOpen("wb");
01023 if (!file)
01024 break;
01025 
01026 do 
01027 {
01028 MRV_COUT << "ACTIVE: " << currentClusters << endl;
01029 
01030 if (sizeof(MRB_Header) != fwrite(&header, 1, sizeof(MRB_Header), file)) break;
01031 MRV_COUT << "points: " << points->NumItems() << endl;
01032 if (points->FWrite(file)) break;
01033 MRV_COUT << "faces: " << faces.NumItems() << endl;
01034 if (faces.FWrite(file)) break;
01035 
01036 if (vertices.NumItems() > 0)
01037 {
01038 MRV_COUT << "root vertices: " << rootVertices.NumItems() << endl;
01039 if (rootVertices.FWrite(file)) break;
01040 MRV_COUT << "vertices: " << vertices.NumItems() << endl;
01041 if (vertices.FWrite(file)) break;
01042 MRV_COUT << "codes: " << vtxCodes.NumItems() << endl;
01043 if (vtxCodes.FWrite(file)) break;
01044 }
01045 
01046 if (clusters.NumItems() > 0)
01047 {
01048 MRV_COUT << "root clusters: " << rootClusters.NumItems() << endl;
01049 if (rootClusters.FWrite(file)) break;
01050 MRV_COUT << "clusters: " << clusters.NumItems() << endl;
01051 if (clusters.FWrite(file)) break;
01052 }
01053 }
01054 while (false);
01055 
01056 if (ferror(file))
01057 perror("MRB write");
01058 fclose(file);
01059 MRV_COUT << "done." << endl;
01060 } while (false);
01061 }
01062 
01063  Bool MRModel::ParseText()
01064 {
01065 String func;
01066 Point vtx;
01067 Int numVertices;
01068 Int faceIdx = 0, vtxOffset, delta;
01069 
01070 Int child[2], depFace[2];
01071 Int vtxId; 
01072 GCLReal cost; 
01073 Point place;
01074 
01075 Int clusID, clusLeft, clusRight;
01076 Point clusOrig;
01077 VecTrans clusAxis;
01078 Vector clusFitNormal;
01079 Point clusMin(vl_0), clusMax(vl_0);
01080 GCLReal clusD;
01081 
01082 ifstream s;
01083 
01084 vtxOffset = -1; // default is 1-based indexes
01085 delta = 0; // original mmf format had no delta-encoding
01086 clusID = -1;
01087 child[0] = -1;
01088 clusLeft = -1;
01089 cost = 0.01;
01090 
01091 s.open(modelFile.GetPath());
01092 if (!s)
01093 {
01094 cerr << "Cannot access " << modelFile.GetPath() << endl;
01095 return(false);
01096 }
01097 
01098 numVertices = 0;
01099 
01100 while (s)
01101 {
01102 if (func.ReadWord(s))
01103 {
01104 if (func == "#$cost" || func == "ve")
01105 s >> vtxId >> cost;
01106 else if (func[0] == '#')
01107 ;
01108 else if (func == "v")
01109 {
01110 s >> vtx[0] >> vtx[1] >> vtx[2];
01111 points->Append(vtx);
01112 numVertices++;
01113 }
01114 else if (func == "f" || func == "t")
01115 {
01116 Int a, b, c;
01117 
01118 s >> a >> b >> c;
01119 
01120 faces.Add(1);
01121 faces.Last().v[0] = a - 1;
01122 faces.Last().v[1] = b - 1;
01123 faces.Last().v[2] = c - 1;
01124 }
01125 else if (func == "set")
01126 { 
01127 func.ReadWord(s);
01128 if (func == "vertex_correction")
01129 {
01130 // add vertex_correction to indexes to get 1-based
01131 // indexing. We use 0-based indexing, hence the
01132 // -1.
01133 s >> vtxOffset;
01134 vtxOffset = vtxOffset - 1;
01135 }
01136 else if (func == "delta_encoding")
01137 s >> delta;
01138 else
01139 cerr << "(ParseMMF) *** Ignoring unknown set variable: "
01140 << func << endl;
01141 }
01142 else if (func == "%SMF" || func == "#$SMF")
01143 {
01144 GCLReal version;
01145 s >> version;
01146 if (version < 1.0)
01147 vtxOffset = 0; // version 0 had 0-based offsets
01148 }
01149 
01150 // === vertex-cluster stuff
01151 else if (func == "v%")
01152 // a vertex contraction
01153 {
01154 Char gobbleBracket;
01155 
01156 // add previous contraction
01157 if (child[0] >= 0)
01158 AddContraction(child[0] + vtxOffset, child[1] + vtxOffset, 
01159 depFace[0] - 1, depFace[1] - 1, cost, place, delta);
01160 
01161 // read in start of new contraction
01162 ChompWhiteSpace(s);
01163 if (s.peek() == '(')
01164 s >> gobbleBracket;
01165 s >> child[0] >> child[1];
01166 ChompWhiteSpace(s);
01167 if (s.peek() == ')')
01168 s >> gobbleBracket;
01169 s >> place[0] >> place[1] >> place[2];
01170 faceIdx = 0;
01171 depFace[0] = depFace[1] = 0;
01172 cost += 0.01; // assume constant cost per contraction if
01173 // none is specified in the file.
01174 }
01175 else if (func == "f-")
01176 {
01177 // dependent face id of current contraction
01178 s >> depFace[faceIdx];
01179 faceIdx ^= 1;
01180 }
01181 
01182 // === face-cluster stuff
01183 else if (func == "f^")
01184 {
01185 if (clusID < 0)
01186 clusID = faces.NumItems(); // first cluster!
01187 
01188 // add previous cluster record
01189 if (clusLeft > 0)
01190 {
01191 AddCluster(clusLeft, clusRight, clusOrig, clusAxis,
01192 clusFitNormal, clusD, clusMin, clusMax, clusID++);
01193 }
01194 s >> clusLeft >> clusRight;
01195 }
01196 else if (func == "fo")
01197 s >> clusOrig[0] >> clusOrig[1] >> clusOrig[2];
01198 else if (func == "fe")
01199 {
01200 s >> clusAxis[0][0] >> clusAxis[0][1] >> clusAxis[0][2];
01201 s >> clusAxis[1][0] >> clusAxis[1][1] >> clusAxis[1][2];
01202 s >> clusAxis[2][0] >> clusAxis[2][1] >> clusAxis[2][2];
01203 }
01204 else if (func == "fd")
01205 s >> clusD;
01206 else if (func == "fn")
01207 s >> clusFitNormal[0] >> clusFitNormal[1] >> clusFitNormal[2];
01208 else if (func == "fx")
01209 {
01210 s >> clusMin[0] >> clusMin[1] >> clusMin[2];
01211 s >> clusMax[0] >> clusMax[1] >> clusMax[2];
01212 }
01213 else if (func == "fc")
01214 ; // cost -- ignore it.
01215 
01216 // unrecognized!
01217 else
01218 cerr << "(ParseMMF) *** Ignoring unknown token: " << func << endl;
01219 
01220 func.ReadLine(s); // ignore rest of line
01221 }
01222 }
01223 
01224 s.close();
01225 
01226 if (child[0] >= 0)
01227 AddContraction(child[0] + vtxOffset, child[1] + vtxOffset, 
01228 depFace[0] - 1, depFace[1] - 1, cost, place, delta);
01229 
01230 if (clusLeft > 0)
01231 AddCluster(clusLeft, clusRight, clusOrig, clusAxis,
01232 clusFitNormal, clusD, clusMin, clusMax, clusID++);
01233 
01234 if (clusID > 0)
01235 clustersActive.SetSize(clusID);
01236 
01237 MRV_COUT << "Read " << numVertices << " vertices and " << faces.NumItems()
01238 << " faces." << endl;
01239 
01240 return(true);
01241 }
01242 
01243  Bool MRModel::Parse(StrConst filename)
01244 {
01245 Bool result;
01246 
01247 if (!points)
01248 points = new PointList;
01249 
01250 modelFile.SetPath(filename);
01251 
01252 if (modelFile.GetExtension() == "mrb")
01253 result = ParseBinary();
01254 else 
01255 result = ParseText();
01256 
01257 if (!result)
01258 return(false);
01259 
01260 MRV_COUT << "There are " << vertices.NumItems() << " vertex contractions, "
01261 << clusters.NumItems() << " face clusters." << endl;
01262 
01263 MRV_COUT << "MEMORY:" << endl;
01264 if (points)
01265 MRV_COUT << " points " << sizeof(Point) * points->NumItems() / 1024.0 << endl;
01266 if (colours)
01267 MRV_COUT << " colours " << sizeof(Colour) * colours->NumItems() / 1024.0 << endl;
01268 MRV_COUT << " indexes " << sizeof(FaceIdx) * faces.NumItems() / 1024.0 << endl;
01269 MRV_COUT << " vtxFaces " << sizeof(FaceIdx) * vtxFaces.NumItems() / 1024.0 << endl;
01270 MRV_COUT << " vtxCodes " << sizeof(MRCodes) * vtxCodes.NumItems() / 1024.0 << endl;
01271 MRV_COUT << " vertices " << sizeof(MRVertex) * vertices.NumItems() / 1024.0 << endl;
01272 MRV_COUT << " clusters " << sizeof(FaceCluster) * clusters.NumItems() / 1024.0 << endl;
01273 
01274 PrepareModel();
01275 
01276 return(true);
01277 }
01278 
01279  Void MRModel::DrawClusterFaces(Int ic, Renderer &r)
01280 {
01281 if (IsFace(ic))
01282 {
01283 PointList &pts = *points;
01284 Int *triIdx = faces[ic].v;
01285 Vector normal;
01286 
01287 normal = FaceAreaNormal(ic);
01288 
01289 r .Begin(scPrimitive::sRenderStyle)
01290 .N(norm(normal))
01291 .P(pts[triIdx[0]])
01292 .P(pts[triIdx[1]])
01293 .P(pts[triIdx[2]])
01294 .End();
01295 }
01296 else
01297 {
01298 FaceCluster &mrf = Cluster(ic);
01299 
01300 if (flags.IsSet(MRM_Ordered) && IsFace(mrf.child[0]) && IsFace(mrf.child[1]))
01301 {
01302 for (Int i = mrf.child[0]; i <= mrf.child[1]; i++)
01303 DrawClusterFaces(i, r);
01304 }
01305 
01306 DrawClusterFaces(mrf.child[0], r);
01307 DrawClusterFaces(mrf.child[1], r);
01308 } 
01309 }
01310 
01311  Void MRModel::Draw(Renderer &r)
01312 {
01313 Int i;
01314 Int *idx;
01315 Bool hasVF = (vtxFaces.NumItems() > 0);
01316 
01317 if (colourFaces && clusterColours.NumItems() == 0)
01318 CreateClusterColours();
01319 
01320 if (showFaces)
01321 {
01322 if (colourFaces)
01323 {
01324 for (i = 0; i < clustersActive.NumItems(); i++)
01325 if (clustersActive[i])
01326 {
01327 r.C(clusterColours[i]);
01328 DrawClusterFaces(i, r);
01329 }
01330 }
01331 else
01332 {
01333 r.C(colour);
01334 for (i = 0; i < faces.NumItems(); i++)
01335 {
01336 if (hasVF)
01337 {
01338 if (!vtxFlags[i].IsSet(MRV_FaceActive))
01339 continue;
01340 idx = vtxFaces[i].v;
01341 }
01342 else
01343 idx = faces[i].v;
01344 
01345 // XXX shouldn't need norm()'s here, but MESA has prec. bug with
01346 // very small normals when GL_NORMALIZE... need workaround
01347 
01348 r.Begin(scPrimitive::sRenderStyle);
01349 if (vertices.NumItems() > 0)
01350 {
01351 if (colours)
01352 r
01353 .N(norm(vertices[idx[0]].areaNormal))
01354 .C((*colours)[idx[0]])
01355 .P((*points)[idx[0]])
01356 .N(norm(vertices[idx[1]].areaNormal))
01357 .C((*colours)[idx[1]])
01358 .P((*points)[idx[1]])
01359 .N(norm(vertices[idx[2]].areaNormal))
01360 .C((*colours)[idx[2]])
01361 .P((*points)[idx[2]]);
01362 else 
01363 r
01364 .N(norm(vertices[idx[0]].areaNormal))
01365 .P((*points)[idx[0]])
01366 .N(norm(vertices[idx[1]].areaNormal))
01367 .P((*points)[idx[1]])
01368 .N(norm(vertices[idx[2]].areaNormal))
01369 .P((*points)[idx[2]]);
01370 }
01371 else
01372 {
01373 Vector areaNormal;
01374 
01375 CalcTriAreaNormal(
01376 (*points)[idx[0]],
01377 (*points)[idx[1]],
01378 (*points)[idx[2]],
01379 areaNormal
01380 );
01381 
01382 r.N(norm(areaNormal));
01383 
01384 if (colours)
01385 r .C((*colours)[idx[0]])
01386 .P((*points)[idx[0]])
01387 .C((*colours)[idx[1]])
01388 .P((*points)[idx[1]])
01389 .C((*colours)[idx[2]])
01390 .P((*points)[idx[2]]);
01391 else
01392 {
01393 r .P((*points)[idx[0]])
01394 .P((*points)[idx[1]])
01395 .P((*points)[idx[2]]);
01396 }
01397 }
01398 r.End();
01399 }
01400 }
01401 }
01402 
01403 if (showMeta)
01404 {
01405 if (clustersActive.NumItems() > 0)
01406 DrawClusters(r);
01407 else if (vertices.NumItems() > 0)
01408 DrawVertices(r);
01409 }
01410 }
01411 
01412  Void MRModel::CreateClusterColours()
01413 {
01414 if (clustersActive.NumItems() > 0)
01415 {
01416 Int i, fc1, fc2;
01417 Colour c;
01418 Double area1, area2;
01419 
01420 clusterColours.SetSize(clustersActive.NumItems());
01421 
01422 if (!sAvgClusColours)
01423 {
01424 for (i = 0; i < faces.NumItems(); i++)
01425 clusterColours[i] = HSVCol(drand48() * 360.0, 1.0, 1.0);
01426 for (i = lastClusterID; i <= firstClusterID; i++)
01427 {
01428 fc1 = Cluster(i).child[0];
01429 fc2 = Cluster(i).child[1];
01430 // XXX fix when we store face areaNormals
01431 if (IsFace(fc1))
01432 area1 = len(FaceAreaNormal(fc1));
01433 else
01434 area1 = Cluster(fc1).totArea;
01435 
01436 if (IsFace(fc2))
01437 area2 = len(FaceAreaNormal(fc2));
01438 else
01439 area2 = Cluster(fc2).totArea;
01440 
01441 if (area1 > area2)
01442 c = clusterColours[fc1];
01443 else
01444 c = clusterColours[fc2];
01445 
01446 clusterColours[i] = c;
01447 }
01448 }
01449 else
01450 {
01451 for (i = 0; i < faces.NumItems(); i++)
01452 clusterColours[i] = HSVCol(drand48() * 360.0, 1.0, 1.0);
01453 for (i = lastClusterID; i <= firstClusterID; i++)
01454 {
01455 c = clusterColours[Cluster(i).child[0]];
01456 c += clusterColours[Cluster(i).child[1]];
01457 c /= 2.0;
01458 clusterColours[i] = c;
01459 }
01460 }
01461 }
01462 }
01463 
01464  Void MRModel::DrawClusters(Renderer &r)
01466 {
01467 Int i;
01468 
01469 for (i = 0; i < clustersActive.NumItems(); i++)
01470 if (clustersActive[i])
01471 if (!IsFace(i))
01472 {
01473 if (!showFaces && colourFaces)
01474 r.C(Colour4(clusterColours[i], 0.5));
01475 else
01476 r.C(Colour4(colour, 0.5));
01477 Cluster(i).Draw(r);
01478 }
01479 else if (!showFaces)
01480 {
01481 if (colourFaces)
01482 r.C(clusterColours[i]);
01483 else
01484 r.C(cYellow);
01485 DrawClusterFaces(i, r);
01486 }
01487 }
01488 
01489  Void MRModel::DrawVertices(Renderer &r)
01491 {
01492 Int i;
01493 
01494 r.C(Colour4(cGreen, 0.5));
01495 
01496 for (i = 0; i < vertices.NumItems(); i++)
01497 if (vtxFlags[i].IsSet(MRV_Active))
01498 {
01499 r.N(vertices[i].areaNormal);
01500 DrawCircle(r, (*points)[i],
01501 norm(vertices[i].areaNormal), 
01502 sqrt(len(vertices[i].areaNormal) / vl_pi)
01503 );
01504 }
01505 }
01506 
01507  Void MRModel::SimplestModel()
01508 {
01509 Int i;
01510 
01511 AdaptClusters(0);
01512 
01513 for (i = 0; i < vertices.NumItems(); i++)
01514 {
01515 MRVertex &v = vertices[i];
01516 
01517 if (v.CanContract(i, vtxFlags))
01518 v.Contract(i, vtxFlags);
01519 }
01520 
01521 lastComplexity = 0.0;
01522 AdjustLeafFaces();
01523 }
01524 
01525  Void MRModel::MostComplexModel()
01526 {
01527 Int i;
01528 
01529 AdaptClusters(faces.NumItems());
01530 
01531 for (i = vertices.NumItems() - 1; i >= 0; i--)
01532 {
01533 MRVertex &v = vertices[i];
01534 
01535 if (v.CanExpand(i, vtxFlags))
01536 v.Expand(i, vtxFlags);
01537 }
01538 
01539 lastComplexity = 1.0;
01540 AdjustLeafFaces();
01541 }
01542 
01543  Vector MRModel::FaceAreaNormal(Int faceIdx)
01544 {
01545 Vector an;
01546 Int *triIdx = faces[faceIdx].v;
01547 
01548 CalcTriAreaNormal((*points)[triIdx[0]],
01549 (*points)[triIdx[1]],
01550 (*points)[triIdx[2]],
01551 an);
01552 
01553 return(0.5 * an);
01554 }
01555 
01556  Void MRModel::UpdateBounds(Point &min, Point &max,
01557 const Transform &t)
01558 {
01559 Int i;
01560 
01561 if (vtxFaces.NumItems() > 0)
01562 {
01563 for (i = 0; i < vtxFaces.NumItems(); i++)
01564 if (vtxFlags[i].IsSet(MRV_FaceActive))
01565 {
01566 				::UpdateBounds(xform(t, points->Item(vtxFaces[i].v[0])), min, max);
01567 				::UpdateBounds(xform(t, points->Item(vtxFaces[i].v[1])), min, max);
01568 				::UpdateBounds(xform(t, points->Item(vtxFaces[i].v[2])), min, max);
01569 }
01570 }
01571 else
01572 for (i = 0; i < points->NumItems(); i++)
01573 			::UpdateBounds(xform(t, points->Item(i)), min, max);
01574 }
01575 
01576 // --- scMRModel methods ------------------------------------------------------
01577 
01578 
01579 GCLReal scMRModel::complexity = 0.1;
01580 
01581  scMRModel::scMRModel() : scPrimitive(pMRModel), model(), currentComplexity(0.0)
01582 {
01583 }
01584 
01585  Void scMRModel::Draw(Renderer &r, SLContext *context)
01586 {
01587 Colour *cPtr;
01588 ColourList *cClrs;
01589 
01590 if (cPtr = SC_GET(Colour))
01591 model.colour = *cPtr;
01592 if (!model.colours && (cClrs = SC_GET(Colours)))
01593 {
01594 if (cClrs->NumItems() == model.points->NumItems())
01595 model.colours = cClrs;
01596 else
01597 cerr << "ignoring bad colours list in MRModel" << endl;
01598 }
01599 
01600 model.AdaptComplexity(complexity);
01601 model.Draw(r);
01602 }
01603 
01604  Void scMRModel::DecimateSelf(Decimator &dec)
01605 { 
01606 if (dec.flags & DecIgnoreMRM)
01607 return;
01608 
01609 Int i, j;
01610 FaceIdx fi;
01611 Bool changed;
01612 
01613 dec.flags.Set(DecIsMRM);
01614 dec.context->Set(aPoints, (scPoints*) model.points);
01615 
01616 changed = true;
01617 
01618 if (model.vtxFaces.NumItems() > 0)
01619 {
01620 Index *map = 0;
01621 
01622 model.AdaptComplexity(complexity);
01623 
01624 if (dec.flags.IsSet(DecUseMaster))
01625 {
01626 // we want to add only those points that are part of
01627 // the current model, so need to remap...
01628 
01629 dec.pointsAccNum = dec.pointsAcc->NumItems();
01630 
01631 map = new Index[model.points->NumItems()];
01632 for (i = 0; i < model.points->NumItems(); i++)
01633 map[i] = -1;
01634 }
01635 
01636 for (i = 0; i < model.faces.NumItems(); i++)
01637 if (model.vtxFlags[i].IsSet(MRV_FaceActive))
01638 {
01639 fi = model.vtxFaces[i];
01640 
01641 if (map)
01642 for (j = 0; j < 3; j++)
01643 {
01644 if (map[fi.v[j]] < 0)
01645 {
01646 map[fi.v[j]] = dec.pointsAcc->NumItems();
01647 dec.pointsAcc->Append(xform(dec.transAcc, model.points->Item(fi.v[j])));
01648 }
01649 fi.v[j] = map[fi.v[j]];
01650 }
01651 else
01652 {
01653 fi.v[0] += dec.pointsAccNum;
01654 fi.v[1] += dec.pointsAccNum;
01655 fi.v[2] += dec.pointsAccNum;
01656 }
01657 dec.HandlePoly(3, fi.v, changed);
01658 changed = false;
01659 dec.decNum++;
01660 }
01661 
01662 delete[] map;
01663 }
01664 else
01665 {
01666 // standard
01667 if (dec.flags.IsSet(DecUseMaster))
01668 {
01669 dec.pointsAccNum = dec.pointsAcc->NumItems();
01670 
01671 dec.pointsAcc->Add(model.points->NumItems());
01672 // apply the current model transform to the new points
01673 i = dec.pointsAccNum;
01674 for (j = 0; j < model.points->NumItems(); j++)
01675 dec.pointsAcc->Item(i++) = 
01676 xform(dec.transAcc, model.points->Item(j));
01677 }
01678 
01679 for (i = 0; i < model.faces.NumItems(); i++)
01680 {
01681 fi = model.faces[i];
01682 
01683 fi.v[0] += dec.pointsAccNum;
01684 fi.v[1] += dec.pointsAccNum;
01685 fi.v[2] += dec.pointsAccNum;
01686 
01687 dec.HandlePoly(3, fi.v, changed);
01688 changed = false;
01689 dec.decNum++;
01690 }
01691 }
01692 
01693 dec.context->Set(aPoints, 0);
01694 dec.flags.UnSet(DecIsMRM);
01695 }
01696 
01697  Void scMRModel::SetComplexity(GCLReal comp)
01698 {
01699 complexity = comp;
01700 };
01701 
01702  GCLReal scMRModel::GetComplexity()
01703 {
01704 return(complexity);
01705 };
01706 
01707  Void scMRModel::UpdateBounds(Point &min, Point &max,
01708 const Transform &t)
01709 {
01710 model.UpdateBounds(min, max, t);
01711 }
01712 
01713 #include "gcl/SceneLang.h"
01714 
01715  scScenePtr ParseMMFFile(const Char *filename)
01716 {
01717 scScenePtr result;
01718 scMRModel *model;
01719 
01720 result = slBeginObject(filename);
01721 model = (scMRModel*) slObject("mr-model");
01722 model->model.points = new scPoints;
01723 slEndObject();
01724 
01725 model->model.Parse(filename);
01726 
01727 return(result);
01728 }
01729 
01730 // --- ModelsFinder methods ---------------------------------------------------
01731 
01732 
01733  Void MRModelsFinder::Start()
01734 {
01735 scSceneAction::Start();
01736 models.Clear();
01737 }
01738 
01739  Void MRModelsFinder::Primitive(scPrimitive *sp)
01740 {
01741 if (sp->PrimID() == pMRModel)
01742 models.Append(&((scMRModel*) sp)->model);
01743 }

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

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