ROOT logo
// $Id: HTriMesh.cxx 2548 2011-10-10 07:03:57Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

#include "HTriMesh.h"
#include "HTriMesh.c7"

// HTriMesh

//______________________________________________________________________________
//
// Hierarhical mesh
//
// Consists of:
// a) high-level hierarhical subdivision
//    all hierarchy represented by a single TringTvor;
//    nodes point into this tvor to identify triangles;
//    ?? depth first or breadth first ??
//    breadth first keeps triangles from a given level together
//    - good for opcode, to construct full tree at some level;
//      is this good? is it needed?
//    - also good for rendering, as some level will be selected at a given
//      distance (in space approach mode);
//    depth first keeps one brach together
//    - good for recursive queries / descends?
// b) low-level triangle soup attached to a leaf-node
//    for now, keep all of them in own TringTvor
//
// In principle could have several a-like layers.
// Or simplify the thing by always having a single a-layer -- but this then
// leads to duplication of vertices.
//
// Hmmh ... aren't vertices always shared?
// Yes ... but at some point I'd like to move leaf-vertices into separate
// meshes, managed by separate tringulas.
//
// So? At this intermediate level ... what do I do?
// Duplicate a-level vertices when creating b-mesh -- to keep Tringula ok.
// Then, it will also become important if one sees Flyers -- checking whole
// bounding volume of the triangle. Hmm, all Extendios ... but they don't go
// that hight so one could just hack highest point.
//
// 


ClassImp(HTriMesh);

//==============================================================================

void HTriMesh::_init()
{}

HTriMesh::HTriMesh(const Text_t* n, const Text_t* t) :
  TriMesh(n, t)
{
  _init();
}

HTriMesh::~HTriMesh()
{}

//==============================================================================

void HTriMesh::PrintLevels() const
{
  for (Int_t i = 0; i <= mMaxLevel; ++i)
  {
    const HLevel &l = mLevels[i];
    printf("%2d %2d %6d %6d %6d %zu\n", i, l.fLevel, l.fFirstT, l.fNT, l.LastT(), l.fNodes.size());
  }
}

//==============================================================================

void HTriMesh::subdivide_hierarhical(TringTvorSubdivider& tts)
{
  // Input level with parent nodes
  //       starting triangle index, or reference to it
  //       edge map
  // Assumes triangles and vertices are already allocated.
  //   Uses some function to do sub-division.
  //   Will I need to move them afterwards? ParaSurf knows ...

  HLevel &prev_level = mLevels[tts.fCurLevel];
  HLevel &new_level  = mLevels[tts.fCurLevel + 1];

  assert(prev_level.fLevel == tts.fCurLevel);
  assert(prev_level.fFirstT + prev_level.fNT == tts.fCurT);

  new_level.Init(tts.fCurLevel + 1, tts.fCurT, 4 * prev_level.fNT, prev_level.fNT);

  printf("HTriMesh::subdivide_hierarhical lvl=%d, t0_in=%d, nt_in=%d; current_t=%d, current_v=%d\n",
	 tts.fCurLevel, prev_level.fFirstT, prev_level.fNT, tts.fCurT, tts.fCurV);
  fflush(stdout);

  for (vpHNode_i ni = prev_level.fNodes.begin(); ni != prev_level.fNodes.end(); ++ni)
  {
    HNode &prev_node = **ni;
    // printf("  prv_level size=%zu, capacity=%zu\n", prev_node.fSubNodes.size(), prev_node.fSubNodes.capacity());
    for (Int_t t = prev_node.FirstT(); t <= prev_node.LastT(); ++t)
    {
      Int_t first_t = tts.SubdivideTriangle(t);
      // printf("    t=%4d, first_t=%d\n", t, first_t);
      fflush(stdout);
      prev_node.fSubNodes.push_back(new HNode(t, first_t, 4));
      new_level.fNodes.push_back(prev_node.fSubNodes.back());
    }
    // printf("  prv_level size=%zu, capacity=%zu\n", prev_node.fSubNodes.size(), prev_node.fSubNodes.capacity());
  }

  printf("  new_level size=%zu, capacity=%zu\n", new_level.fNodes.size(), new_level.fNodes.capacity());

  ++tts.fCurLevel;
}

void HTriMesh::subdivide_leaf(TringTvorSubdivider& tts, Int_t n_leaf)
{
  assert((size_t) tts.fCurLevel == mLevels.size() - 2);

  HLevel &prev_level = mLevels[tts.fCurLevel];
  HLevel &new_level  = mLevels[tts.fCurLevel + 1];

  new_level.Init(tts.fCurLevel + 1, tts.fCurT, (1 << 2*n_leaf) * prev_level.fNT, prev_level.fNT);

  printf("HTriMesh::subdivide_leaf lvl=%d, t0_in=%d, nt_in=%d; current_t=%d, current_v=%d\n",
	 tts.fCurLevel, prev_level.fFirstT, prev_level.fNT, tts.fCurT, tts.fCurV);
  fflush(stdout);

  for (vpHNode_i ni = prev_level.fNodes.begin(); ni != prev_level.fNodes.end(); ++ni)
  {
    HNode &prev_node = **ni;
    for (Int_t t = prev_node.FirstT(); t <= prev_node.LastT(); ++t)
    {
      Int_t *v = tts.fTvor.Triangle(t);
      Int_t first_t = tts.fCurT;
      subdivide_leaf_rec(tts, v[0], v[1], v[2], n_leaf - 1);

      // or sth like this ... recheck!!
      assert(tts.fCurT - first_t == 4 << (2 * (n_leaf - 1)));

      prev_node.fSubNodes.push_back(new HNode(t, first_t, tts.fCurT - first_t));
      new_level.fNodes.push_back(prev_node.fSubNodes.back());
    }

    // printf("  prv_level size=%zu, capacity=%zu\n", prev_node.fSubNodes.size(), prev_node.fSubNodes.capacity());
  }

  printf("  new_level size=%zu, capacity=%zu\n", new_level.fNodes.size(), new_level.fNodes.capacity());

  ++tts.fCurLevel;
}

void HTriMesh::subdivide_leaf_rec(TringTvorSubdivider& tts, Int_t v0, Int_t v1, Int_t v2, Int_t depth)
{
  Int_t u0 = tts.SubdivideEdge(v0, v1);
  Int_t u1 = tts.SubdivideEdge(v1, v2);
  Int_t u2 = tts.SubdivideEdge(v2, v0);

  if (depth > 0)
  {
    --depth;
    subdivide_leaf_rec(tts, v0, u0, u2, depth);
    subdivide_leaf_rec(tts, u0, v1, u1, depth);
    subdivide_leaf_rec(tts, u1, v2, u2, depth);
    subdivide_leaf_rec(tts, u2, u0, u1, depth);
  }
  else
  {
    tts.fTvor.SetTriangle(tts.fCurT++, v0, u0, u2);
    tts.fTvor.SetTriangle(tts.fCurT++, u0, v1, u1);
    tts.fTvor.SetTriangle(tts.fCurT++, u1, v2, u2);
    tts.fTvor.SetTriangle(tts.fCurT++, u2, u0, u1);
  }
}

//------------------------------------------------------------------------------

void HTriMesh::Subdivide(Int_t n_hierarhical, Int_t n_leaf)
{
  static const Exc_t _eh("HTriMesh::Subdivide ");

  assert_tvor(_eh);
  TringTvor &T = *mTTvor;

  T.DeleteSecondaryArrays();

  mRootNode.Init(-1, 0, T.NTrings());

  mLevels.resize(1 + n_hierarhical + (n_leaf > 0 ? 1 : 0));
  mLevels[0].Init(0, 0, T.NTrings(), T.NTrings());
  mLevels[0].fNodes.push_back(&mRootNode);

  TringTvorSubdivider tts(T);
  tts.BeginSubdivision(n_hierarhical, n_leaf);

  for (Int_t i = 0; i < n_hierarhical; ++i)
  {
    printf("HTriMesh::Subdivide hierarhical, i = %d\n", i);
    fflush(stdout);
    subdivide_hierarhical(tts);
  }

  if (n_leaf > 0)
  {
    printf("HTriMesh::Subdivide leaf, going in for n_leaf = %d\n", n_leaf);
    fflush(stdout);
    subdivide_leaf(tts, n_leaf);
  }

  tts.EndSubdivision();

  mMaxLevel = mLevels.size() - 1;
}


//==============================================================================
// HTriMesh::TringTvorSubdivider
//==============================================================================

void HTriMesh::TringTvorSubdivider::BeginSubdivision(Int_t n_hierarhical, Int_t n_leaf)
{
  // Initialization function. Could be joined into ctor.

  fCurV = fTvor.NVerts();
  fCurT = fTvor.NTrings();
  fCurLevel = 0;

  // Count edges
  Int_t ne = TriMesh::fill_edge_map(fTvor.NTrings(), fTvor.Trings(), fEdgeMap, fTvor.mNVerts);
  fEdgeMap.clear();

  Int_t nnv = 0;
  Int_t nep = ne;
  Int_t nnt = 0;
  Int_t ntp = fCurT;
  for (Int_t i = 0; i < n_hierarhical; ++i)
  {
    nnv += nep;
    nep  = 2 * nep + 3 * ntp;
    ntp *= 4;
    nnt += ntp;
    printf("BS-h i=%d: nnv=%d nnt=%d;  nep=%d ntp=%d\n", i, nnv, nnt, nep, ntp);
  }
  Int_t nt_hierarhical = nnt;
  for (Int_t i = 0; i < n_leaf; ++i)
  {
    nnv += nep;
    nep  = 2 * nep + 3 * ntp;
    ntp *= 4;
    nnt += ntp;
    printf("BS-l i=%d: nnv=%d nnt=%d;  nep=%d ntp=%d\n", i, nnv, nnt, nep, ntp);
  }
  Int_t nt_leaf = ntp;

  fTvor.AddVertices (nnv);
  fTvor.AddTriangles(nt_hierarhical + nt_leaf);
}

Int_t HTriMesh::TringTvorSubdivider::SubdivideEdge(Int_t v0, Int_t v1)
{
  // Returns index of vertex between v0 and v1.
  // It is possible that the edge was already subdivided.
  // When a new vertex is created, it is inserted into fEdgeMap.

  HTriMesh::hEdge_i i = fEdgeMap.find(Edge(v0, v1));
  if (i != fEdgeMap.end())
    return i->second;

  HPointF &p0 = * (HPointF*) fTvor.Vertex(v0);
  HPointF &p1 = * (HPointF*) fTvor.Vertex(v1);
  HPointF &m  = * (HPointF*) fTvor.Vertex(fCurV);

  m = 0.5f * (p0 + p1);

  fEdgeMap.insert(make_pair(Edge(v0, v1), fCurV));

  // Edge e(v0,v1);
  // printf("  adding vertex %d for edge(%d, %d)\n", fCurV, e.v1, e.v2);

  return fCurV++;
}

Int_t HTriMesh::TringTvorSubdivider::SubdivideTriangle(Int_t t)
{
  // Returns triangle index of the first new triangle.

  // outer (old) and inner (new) triangles
  Int_t *o = fTvor.Triangle(t);
  Int_t  i[3] = {
    SubdivideEdge(o[0], o[1]),
    SubdivideEdge(o[1], o[2]),
    SubdivideEdge(o[2], o[0])
  };

  Int_t fti = fCurT;

  fTvor.SetTriangle(fCurT++, o[0], i[0], i[2]);
  fTvor.SetTriangle(fCurT++, i[0], o[1], i[1]);
  fTvor.SetTriangle(fCurT++, i[1], o[2], i[2]);
  fTvor.SetTriangle(fCurT++, i[2], i[0], i[1]);

  return fti;
}

void HTriMesh::TringTvorSubdivider::EndSubdivision()
{
  // Check if total n vertices/triangles matches with current counters.

  printf("HTriMesh::TringTvorSubdivider::EndSubdivision tring(%d,%d), vert(%d, %d)\n",
	 fCurT, fTvor.NTrings(), fCurV, fTvor.NVerts());
  assert(fCurT == fTvor.NTrings());
  assert(fCurV == fTvor.NVerts());
}
 HTriMesh.cxx:1
 HTriMesh.cxx:2
 HTriMesh.cxx:3
 HTriMesh.cxx:4
 HTriMesh.cxx:5
 HTriMesh.cxx:6
 HTriMesh.cxx:7
 HTriMesh.cxx:8
 HTriMesh.cxx:9
 HTriMesh.cxx:10
 HTriMesh.cxx:11
 HTriMesh.cxx:12
 HTriMesh.cxx:13
 HTriMesh.cxx:14
 HTriMesh.cxx:15
 HTriMesh.cxx:16
 HTriMesh.cxx:17
 HTriMesh.cxx:18
 HTriMesh.cxx:19
 HTriMesh.cxx:20
 HTriMesh.cxx:21
 HTriMesh.cxx:22
 HTriMesh.cxx:23
 HTriMesh.cxx:24
 HTriMesh.cxx:25
 HTriMesh.cxx:26
 HTriMesh.cxx:27
 HTriMesh.cxx:28
 HTriMesh.cxx:29
 HTriMesh.cxx:30
 HTriMesh.cxx:31
 HTriMesh.cxx:32
 HTriMesh.cxx:33
 HTriMesh.cxx:34
 HTriMesh.cxx:35
 HTriMesh.cxx:36
 HTriMesh.cxx:37
 HTriMesh.cxx:38
 HTriMesh.cxx:39
 HTriMesh.cxx:40
 HTriMesh.cxx:41
 HTriMesh.cxx:42
 HTriMesh.cxx:43
 HTriMesh.cxx:44
 HTriMesh.cxx:45
 HTriMesh.cxx:46
 HTriMesh.cxx:47
 HTriMesh.cxx:48
 HTriMesh.cxx:49
 HTriMesh.cxx:50
 HTriMesh.cxx:51
 HTriMesh.cxx:52
 HTriMesh.cxx:53
 HTriMesh.cxx:54
 HTriMesh.cxx:55
 HTriMesh.cxx:56
 HTriMesh.cxx:57
 HTriMesh.cxx:58
 HTriMesh.cxx:59
 HTriMesh.cxx:60
 HTriMesh.cxx:61
 HTriMesh.cxx:62
 HTriMesh.cxx:63
 HTriMesh.cxx:64
 HTriMesh.cxx:65
 HTriMesh.cxx:66
 HTriMesh.cxx:67
 HTriMesh.cxx:68
 HTriMesh.cxx:69
 HTriMesh.cxx:70
 HTriMesh.cxx:71
 HTriMesh.cxx:72
 HTriMesh.cxx:73
 HTriMesh.cxx:74
 HTriMesh.cxx:75
 HTriMesh.cxx:76
 HTriMesh.cxx:77
 HTriMesh.cxx:78
 HTriMesh.cxx:79
 HTriMesh.cxx:80
 HTriMesh.cxx:81
 HTriMesh.cxx:82
 HTriMesh.cxx:83
 HTriMesh.cxx:84
 HTriMesh.cxx:85
 HTriMesh.cxx:86
 HTriMesh.cxx:87
 HTriMesh.cxx:88
 HTriMesh.cxx:89
 HTriMesh.cxx:90
 HTriMesh.cxx:91
 HTriMesh.cxx:92
 HTriMesh.cxx:93
 HTriMesh.cxx:94
 HTriMesh.cxx:95
 HTriMesh.cxx:96
 HTriMesh.cxx:97
 HTriMesh.cxx:98
 HTriMesh.cxx:99
 HTriMesh.cxx:100
 HTriMesh.cxx:101
 HTriMesh.cxx:102
 HTriMesh.cxx:103
 HTriMesh.cxx:104
 HTriMesh.cxx:105
 HTriMesh.cxx:106
 HTriMesh.cxx:107
 HTriMesh.cxx:108
 HTriMesh.cxx:109
 HTriMesh.cxx:110
 HTriMesh.cxx:111
 HTriMesh.cxx:112
 HTriMesh.cxx:113
 HTriMesh.cxx:114
 HTriMesh.cxx:115
 HTriMesh.cxx:116
 HTriMesh.cxx:117
 HTriMesh.cxx:118
 HTriMesh.cxx:119
 HTriMesh.cxx:120
 HTriMesh.cxx:121
 HTriMesh.cxx:122
 HTriMesh.cxx:123
 HTriMesh.cxx:124
 HTriMesh.cxx:125
 HTriMesh.cxx:126
 HTriMesh.cxx:127
 HTriMesh.cxx:128
 HTriMesh.cxx:129
 HTriMesh.cxx:130
 HTriMesh.cxx:131
 HTriMesh.cxx:132
 HTriMesh.cxx:133
 HTriMesh.cxx:134
 HTriMesh.cxx:135
 HTriMesh.cxx:136
 HTriMesh.cxx:137
 HTriMesh.cxx:138
 HTriMesh.cxx:139
 HTriMesh.cxx:140
 HTriMesh.cxx:141
 HTriMesh.cxx:142
 HTriMesh.cxx:143
 HTriMesh.cxx:144
 HTriMesh.cxx:145
 HTriMesh.cxx:146
 HTriMesh.cxx:147
 HTriMesh.cxx:148
 HTriMesh.cxx:149
 HTriMesh.cxx:150
 HTriMesh.cxx:151
 HTriMesh.cxx:152
 HTriMesh.cxx:153
 HTriMesh.cxx:154
 HTriMesh.cxx:155
 HTriMesh.cxx:156
 HTriMesh.cxx:157
 HTriMesh.cxx:158
 HTriMesh.cxx:159
 HTriMesh.cxx:160
 HTriMesh.cxx:161
 HTriMesh.cxx:162
 HTriMesh.cxx:163
 HTriMesh.cxx:164
 HTriMesh.cxx:165
 HTriMesh.cxx:166
 HTriMesh.cxx:167
 HTriMesh.cxx:168
 HTriMesh.cxx:169
 HTriMesh.cxx:170
 HTriMesh.cxx:171
 HTriMesh.cxx:172
 HTriMesh.cxx:173
 HTriMesh.cxx:174
 HTriMesh.cxx:175
 HTriMesh.cxx:176
 HTriMesh.cxx:177
 HTriMesh.cxx:178
 HTriMesh.cxx:179
 HTriMesh.cxx:180
 HTriMesh.cxx:181
 HTriMesh.cxx:182
 HTriMesh.cxx:183
 HTriMesh.cxx:184
 HTriMesh.cxx:185
 HTriMesh.cxx:186
 HTriMesh.cxx:187
 HTriMesh.cxx:188
 HTriMesh.cxx:189
 HTriMesh.cxx:190
 HTriMesh.cxx:191
 HTriMesh.cxx:192
 HTriMesh.cxx:193
 HTriMesh.cxx:194
 HTriMesh.cxx:195
 HTriMesh.cxx:196
 HTriMesh.cxx:197
 HTriMesh.cxx:198
 HTriMesh.cxx:199
 HTriMesh.cxx:200
 HTriMesh.cxx:201
 HTriMesh.cxx:202
 HTriMesh.cxx:203
 HTriMesh.cxx:204
 HTriMesh.cxx:205
 HTriMesh.cxx:206
 HTriMesh.cxx:207
 HTriMesh.cxx:208
 HTriMesh.cxx:209
 HTriMesh.cxx:210
 HTriMesh.cxx:211
 HTriMesh.cxx:212
 HTriMesh.cxx:213
 HTriMesh.cxx:214
 HTriMesh.cxx:215
 HTriMesh.cxx:216
 HTriMesh.cxx:217
 HTriMesh.cxx:218
 HTriMesh.cxx:219
 HTriMesh.cxx:220
 HTriMesh.cxx:221
 HTriMesh.cxx:222
 HTriMesh.cxx:223
 HTriMesh.cxx:224
 HTriMesh.cxx:225
 HTriMesh.cxx:226
 HTriMesh.cxx:227
 HTriMesh.cxx:228
 HTriMesh.cxx:229
 HTriMesh.cxx:230
 HTriMesh.cxx:231
 HTriMesh.cxx:232
 HTriMesh.cxx:233
 HTriMesh.cxx:234
 HTriMesh.cxx:235
 HTriMesh.cxx:236
 HTriMesh.cxx:237
 HTriMesh.cxx:238
 HTriMesh.cxx:239
 HTriMesh.cxx:240
 HTriMesh.cxx:241
 HTriMesh.cxx:242
 HTriMesh.cxx:243
 HTriMesh.cxx:244
 HTriMesh.cxx:245
 HTriMesh.cxx:246
 HTriMesh.cxx:247
 HTriMesh.cxx:248
 HTriMesh.cxx:249
 HTriMesh.cxx:250
 HTriMesh.cxx:251
 HTriMesh.cxx:252
 HTriMesh.cxx:253
 HTriMesh.cxx:254
 HTriMesh.cxx:255
 HTriMesh.cxx:256
 HTriMesh.cxx:257
 HTriMesh.cxx:258
 HTriMesh.cxx:259
 HTriMesh.cxx:260
 HTriMesh.cxx:261
 HTriMesh.cxx:262
 HTriMesh.cxx:263
 HTriMesh.cxx:264
 HTriMesh.cxx:265
 HTriMesh.cxx:266
 HTriMesh.cxx:267
 HTriMesh.cxx:268
 HTriMesh.cxx:269
 HTriMesh.cxx:270
 HTriMesh.cxx:271
 HTriMesh.cxx:272
 HTriMesh.cxx:273
 HTriMesh.cxx:274
 HTriMesh.cxx:275
 HTriMesh.cxx:276
 HTriMesh.cxx:277
 HTriMesh.cxx:278
 HTriMesh.cxx:279
 HTriMesh.cxx:280
 HTriMesh.cxx:281
 HTriMesh.cxx:282
 HTriMesh.cxx:283
 HTriMesh.cxx:284
 HTriMesh.cxx:285
 HTriMesh.cxx:286
 HTriMesh.cxx:287
 HTriMesh.cxx:288
 HTriMesh.cxx:289
 HTriMesh.cxx:290
 HTriMesh.cxx:291
 HTriMesh.cxx:292
 HTriMesh.cxx:293
 HTriMesh.cxx:294
 HTriMesh.cxx:295
 HTriMesh.cxx:296
 HTriMesh.cxx:297
 HTriMesh.cxx:298
 HTriMesh.cxx:299
 HTriMesh.cxx:300
 HTriMesh.cxx:301
 HTriMesh.cxx:302
 HTriMesh.cxx:303
 HTriMesh.cxx:304
 HTriMesh.cxx:305
 HTriMesh.cxx:306
 HTriMesh.cxx:307
 HTriMesh.cxx:308
 HTriMesh.cxx:309
 HTriMesh.cxx:310
 HTriMesh.cxx:311
 HTriMesh.cxx:312
 HTriMesh.cxx:313
 HTriMesh.cxx:314
 HTriMesh.cxx:315