예제 #1
0
static void MakePatchCapTexture(PatchMesh &pmesh, Matrix3 &itm, int pstart, int pend, BOOL usePhysUVs) {
	if(pstart == pend)
		return;

	// Find out which verts are used by the cap
	BitArray capVerts(pmesh.numVerts);
	capVerts.ClearAll();
	for(int i = pstart; i < pend; ++i) {
		Patch &p = pmesh.patches[i];
		capVerts.Set(p.v[0]);
		capVerts.Set(p.v[1]);
		capVerts.Set(p.v[2]);
		if(p.type == PATCH_QUAD)
			capVerts.Set(p.v[3]);
		}
	// Minmax the verts involved in X/Y axis and total them
	Box3 bounds;
	int numCapVerts = 0;
	int numCapPatches = pend - pstart;
	IntTab capIndexes;
	capIndexes.SetCount(pmesh.numVerts);
	int baseTVert = pmesh.getNumTVerts();
	for(int i = 0; i < pmesh.numVerts; ++i) {
		if(capVerts[i]) {
			capIndexes[i] = baseTVert + numCapVerts++;
			bounds += pmesh.verts[i].p * itm;
			}
		}
	pmesh.setNumTVerts(baseTVert + numCapVerts, TRUE);
	Point3 s;
    if (usePhysUVs)
        s = Point3(1.0f, 1.0f, 0.0f);
    else
        s = Point3(1.0f / bounds.Width().x, 1.0f / bounds.Width().y, 0.0f);
	Point3 t(-bounds.Min().x, -bounds.Min().y, 0.0f);
	// Do the TVerts
	for(int i = 0; i < pmesh.numVerts; ++i) {
		if(capVerts[i])
			pmesh.setTVert(baseTVert++, ((pmesh.verts[i].p * itm) + t) * s);
		}
	// Do the TVPatches
	for(int i = pstart; i < pend; ++i) {
		Patch &p = pmesh.patches[i];
		TVPatch &tp = pmesh.getTVPatch(i);
		if(p.type == PATCH_TRI)
			tp.setTVerts(capIndexes[p.v[0]], capIndexes[p.v[1]], capIndexes[p.v[2]]);
		else
			tp.setTVerts(capIndexes[p.v[0]], capIndexes[p.v[1]], capIndexes[p.v[2]], capIndexes[p.v[3]]);
		}
	}
예제 #2
0
static void MakeMeshCapTexture(Mesh &mesh, Matrix3 &itm, int fstart, int fend, BOOL usePhysUVs) {
	if(fstart == fend)
		return;
	// Find out which verts are used by the cap
	BitArray capVerts(mesh.numVerts);
	capVerts.ClearAll();
	for(int i = fstart; i < fend; ++i) {
		Face &f = mesh.faces[i];
		capVerts.Set(f.v[0]);
		capVerts.Set(f.v[1]);
		capVerts.Set(f.v[2]);
		}
	// Minmax the verts involved in X/Y axis and total them
	Box3 bounds;
	int numCapVerts = 0;
	int numCapFaces = fend - fstart;
	IntTab capIndexes;
	capIndexes.SetCount(mesh.numVerts);
	int baseTVert = mesh.getNumTVerts();
	for(int i = 0; i < mesh.numVerts; ++i) {
		if(capVerts[i]) {
			capIndexes[i] = baseTVert + numCapVerts++;
			bounds += mesh.verts[i] * itm;
			}
		}
	mesh.setNumTVerts(baseTVert + numCapVerts, TRUE);
	Point3 s;
    if (usePhysUVs)
        s = Point3(1.0f, 1.0f, 0.0f);
    else
        s = Point3(1.0f / bounds.Width().x, 1.0f / bounds.Width().y, 0.0f);

	Point3 t(-bounds.Min().x, -bounds.Min().y, 0.0f);
	// Do the TVerts
	for(int i = 0; i < mesh.numVerts; ++i) {
		if(capVerts[i])
			mesh.setTVert(baseTVert++, ((mesh.verts[i] * itm) + t) * s);
		}
	// Do the TVFaces
	for(int i = fstart; i < fend; ++i) {
		Face &f = mesh.faces[i];
		mesh.tvFace[i] = TVFace(capIndexes[f.v[0]], capIndexes[f.v[1]], capIndexes[f.v[2]]);
		}
	}
// Description: read the specified geometry from the lataDB_ structure and put it in "dom".
//  load_faces: flag, tells if we should read faces definitions in the lata file
//  merge_virtual_elements: flag, if a "VIRTUAL_ELEMENTS" array is present in the lata file,
//   merges these elements to the requested block.
void DomainUnstructured::fill_domain_from_lataDB(const LataDB & lataDB,
                                                 const Domain_Id & id,
                                                 entier load_faces, 
                                                 entier merge_virtual_elements) 
{
  operator=(DomainUnstructured()); // Reset all data.

  id_ = id;
  const LataDBGeometry & geom = lataDB.get_geometry(id.timestep_, id.name_);

  // ********************************
  // 1) Look for the sub-block items to read (parallel computation)
  entier decal_nodes = 0;
  entier decal_elements = 0;
  entier decal_faces = 0;
  entier nb_sommets = -1;
  entier nb_elements = -1;
  entier nb_faces = -1;

  entier domain_has_faces = load_faces && lataDB.field_exists(id.timestep_, id.name_, "FACES");
  
  // Tableau de 3 joints (SOM, ELEM et FACES)
  LataVector<IntTab> joints;
  entier nproc = 1;
  for (entier i_item = 0; i_item < 3; i_item++) {
    LataField_base::Elem_som loc = LataField_base::SOM; (void) loc;
    Nom nom("JOINTS_SOMMETS");
    Nom nom2("SOMMETS");
    if (i_item == 1) {
      loc = LataField_base::ELEM;
      nom = "JOINTS_ELEMENTS";
      nom2 = "ELEMENTS";
    } else if (i_item == 2) {
      loc = LataField_base::FACES;
      nom = "JOINTS_FACES";
      nom2 = "FACES";
    }

    IntTab & joint = joints.add();
    if (lataDB.field_exists(id.timestep_, id.name_, nom)) {
      entier nb_items = lataDB.get_field(id.timestep_, id.name_, nom2, "*").size_;
      IntTab tmp;
      lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, nom, "*"), tmp);
      nproc = tmp.dimension(0);
      // Recalcule la deuxieme colonne en fonction de la premiere
      joint.resize(nproc, 2);
      for (entier i = 0; i < nproc; i++) {
        joint(i, 0) = tmp(i, 0);
        if (i < nproc-1)
          joint(i, 1) = tmp(i+1, 0) - tmp(i, 0);
        else 
          joint(i, 1) = nb_items - tmp(i, 0);
      }
    } 
  }

  if (id_.block_ < 0 || nproc == 1) {
    // read all blocks at once default values are ok
    set_joints(LataField_base::SOM) = joints[0];
    set_joints(LataField_base::ELEM) = joints[1];
    set_joints(LataField_base::FACES) = joints[2];
  } else {
    if (id_.block_ >= nproc) {
      Journal() << "LataFilter::get_geometry : request non existant block " << id.block_ 
                << " in geometry " << id.name_ << endl;
      throw;
    }
    const entier n = id_.block_;
    decal_nodes = joints[0](n, 0);
    nb_sommets = joints[0](n, 1);
    decal_elements = joints[1](n, 0);
    nb_elements = joints[1](n, 1);
    if (domain_has_faces) {
      decal_faces = joints[2](n, 0);
      nb_faces = joints[2](n, 1);
    }
  }

  // ******************************
  // 2) Read nodes, elements and faces data
  elt_type_ = Domain::element_type_from_string(geom.elem_type_);

  lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "SOMMETS", "*"), nodes_, decal_nodes, nb_sommets);
  lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEMENTS", "*"), elements_, decal_elements, nb_elements);
  set_lata_block_offset(LataField_base::SOM, decal_nodes);
  set_lata_block_offset(LataField_base::ELEM, decal_elements);
  if (decal_nodes > 0) {
    // Nodes are stored with global numbering in the lata file: transform to sub_block numbering :
    elements_ -= decal_nodes;
  }
  if (domain_has_faces) {
    set_lata_block_offset(LataField_base::FACES, decal_faces);
    lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "FACES", "*"), faces_, decal_faces, nb_faces);
    if (decal_nodes > 0)
      faces_ -= decal_nodes;
    lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEM_FACES", "*"), elem_faces_, decal_elements, nb_elements);
    if (decal_faces > 0)
      elem_faces_ -= decal_faces;
  }

  // *************************
  // 3) Merge virtual elements if requested
  if (merge_virtual_elements && lataDB.field_exists(id.timestep_, id.name_, "VIRTUAL_ELEMENTS") && id.block_ >= 0) 
    {
      Journal(info_level) << " Merging virtual elements" << endl;
      // joints_virt_elems(sub_block, 0) = index of first virtual element in the VIRTUAL_ELEMENTS array
      IntTab joints_virt_elems;
      // Load the virtual elements (nodes are in global numbering)
      //  First: find the index and number of virtual elements for block number id.block_:
      lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "JOINTS_VIRTUAL_ELEMENTS", "*"), joints_virt_elems);
      entier nb_virt_elems;
      if (id.block_ < nproc-1)
        nb_virt_elems = joints_virt_elems(id.block_+1, 0) - joints_virt_elems(id.block_, 0);
      else
        nb_virt_elems = lataDB.get_field(id.timestep_, id.name_, "VIRTUAL_ELEMENTS", "*").size_ - joints_virt_elems(id.block_, 0);
      Journal(info_level+1) << " Number of virtual elements for block " << id.block_ << "=" << nb_virt_elems << endl;
      //  Second: load the indexes of the virtual elements to load:
      IntTab virt_elems;
      lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "VIRTUAL_ELEMENTS", "*"), virt_elems, joints_virt_elems(id.block_,0), nb_virt_elems);
      set_virt_items(LataField_base::ELEM, virt_elems);

      {
        //  Third: load the virtual elements (virt_elems contains the global indexes of the elements to
        //  load and virt_elem_som will contain global nodes indexes of the virtual elements)
        IntTab virt_elem_som;
        lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEMENTS", "*"), virt_elem_som, virt_elems);
        // Find which virtual nodes are required and load them: virtual nodes to load are
        // all nodes of the virtual elements (they have duplicates).
        ArrOfInt index;
        ArrOfInt & virt_elem_som_array = virt_elem_som; // Array seen as monodimensionnal
        array_sort_indirect(virt_elem_som_array, index);
        // Global nodes indexes of needed virtual nodes 
        ArrOfInt nodes_to_read;
        nodes_to_read.set_smart_resize(1);
        {
          const entier n = index.size_array();
          // Global index of the last loaded node:
          entier last_node = -1;
          // Local index of the new loaded node:
          entier new_node_index = nodes_.dimension(0)-1;
          for (entier i = 0; i < n; i++) {
            // Take nodes to load in ascending order of their global numbers:
            const entier idx = index[i];
            const entier node = virt_elem_som_array[idx];
            if (node != last_node) {
              // Node not yet encountered
              nodes_to_read.append_array(node);
              new_node_index++;
              last_node = node;
            }
            virt_elem_som_array[idx] = new_node_index;
          }
        }
        set_virt_items(LataField_base::SOM, nodes_to_read);
        // Copy virtual elements to elements_
        entier debut = elements_.size_array();
        elements_.resize(elements_.dimension(0) + virt_elem_som.dimension(0),
                         elements_.dimension(1));
        elements_.inject_array(virt_elem_som, virt_elem_som.size_array(), debut);
        // Load virtual nodes
        FloatTab tmp_nodes;
        lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "SOMMETS", "*"), tmp_nodes, nodes_to_read);
        // Copy to nodes_
        debut = nodes_.size_array();
        nodes_.resize(nodes_.dimension(0) + tmp_nodes.dimension(0),
                      nodes_.dimension(1));
        nodes_.inject_array(tmp_nodes, tmp_nodes.size_array(), debut);
      }

      if (domain_has_faces) {
        // Find which virtual faces are required and load them
        // For each virtual element, index of its faces (like virt_elem_som)
        IntTab virt_elem_faces; 
        lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEM_FACES", "*"), virt_elem_faces, virt_elems);
        // Build the list of missing faces:
        ArrOfInt index;
        ArrOfInt & virt_elem_faces_array = virt_elem_faces; // Array seen as monodimensionnal
        array_sort_indirect(virt_elem_faces_array, index);
        ArrOfInt faces_to_read;
        faces_to_read.set_smart_resize(1);
        {
          const entier n = index.size_array();
          // Global index of the last loaded face:
          entier last_face = -1;
          // Local index of the new loaded node:
          entier new_face_index = faces_.dimension(0)-1;
          for (entier i = 0; i < n; i++) {
            // Take nodes to load in ascending order of their global numbers:
            const entier idx = index[i];
            const entier face = virt_elem_faces_array[idx];
            if (face != last_face) {
              // Node not yet encountered
              faces_to_read.append_array(face);
              new_face_index++;
              last_face = face;
            }
            virt_elem_faces_array[idx] = new_face_index;
          }
        }
        set_virt_items(LataField_base::FACES, faces_to_read);
        // Copy virtual elem_faces to elem_faces
        entier debut = elem_faces_.size_array();
        elem_faces_.resize(elem_faces_.dimension(0) + virt_elem_faces.dimension(0),
                           elem_faces_.dimension(1));
        elem_faces_.inject_array(virt_elem_faces, virt_elem_faces.size_array(), debut);

        // Load virtual faces
        IntTab tmp_faces_nodes;
        lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "FACES", "*"), tmp_faces_nodes, faces_to_read);
        // Convert global nodes indexes to local loaded nodes indexes in tmp_faces_nodes
        {
          // sort tmp_faces in ascending order so that the search requires linear time
          ArrOfInt & array_tmp_faces_nodes = tmp_faces_nodes;
          index.reset();
          array_sort_indirect(array_tmp_faces_nodes, index);
          const entier n = array_tmp_faces_nodes.size_array();
          // Take nodes in tmp_faces_nodes in ascending order and find the corresponding node in nodes_to_read
          // (which is also in sorted)
          entier i1; // index in array_tmp_faces_nodes (the current node to convert)
          entier i2 = 0; // index in nodes_to_read
          const entier index_of_first_virtual_node = nodes_.dimension(0) - nb_virt_items(LataField_base::SOM);
          const ArrOfInt & nodes_to_read = get_virt_items(LataField_base::SOM);
          const entier max_i2 = nodes_to_read.size_array();
          for (i1 = 0; i1 < n; i1++) {
            const entier j = index[i1];
            const entier global_node_index_to_find = array_tmp_faces_nodes[j];
            // find the matching node in nodes_to_read (nodes_to_read is in ascending order)
            while (nodes_to_read[i2] != global_node_index_to_find) {
              i2++;
              if (i2 >= max_i2) {
                cerr << "Internal error in DomainUnstructured::fill_domain_from_lataDB:\n"
                     << " node " << global_node_index_to_find << " of a virtual face does not belong to a virtual element" << endl;
//                exit(-1);
              }
            }
            array_tmp_faces_nodes[j] = index_of_first_virtual_node + i2; // index of this node in the local nodes_ array
          }
        }
        // Copy to faces_ array
        debut = faces_.size_array();
        faces_.resize(faces_.dimension(0) + tmp_faces_nodes.dimension(0),
                      faces_.dimension(1));
        faces_.inject_array(tmp_faces_nodes, tmp_faces_nodes.size_array(), debut);
      }
    }
}
예제 #4
0
void DeletePatchParts(PatchMesh *patch, RPatchMesh *rpatch, BitArray &delVerts, BitArray &delPatches) 
{
	int patches = patch->getNumPatches();
	int verts = patch->getNumVerts();
	int vecs = patch->getNumVecs();
	int dest;

	// We treat vectors specially in order to clean up after welds.  First, we tag 'em all,
	// then untag only those on unselected patches so that any dangling vectors will be deleted.
	BitArray delVectors(vecs);
	delVectors.SetAll();

	// Untag vectors that are on nondeleted patches
	int i;
	for (i = 0; i < patches; ++i)
	{
		if (!delPatches[i])
		{
			Patch& p = patch->patches[i];
			int j;
			for (j = 0; j <(p.type * 2); ++j)
			{
				delVectors.Clear(p.vec[j]);
			}
			for (j = 0; j < p.type; ++j)
				delVectors.Clear(p.interior[j]);
		}
	}

	// Make a table of vertices that are still in use -- Used to
	// delete those vertices which are floating, unused, in space.
	BitArray usedVerts(verts);
	usedVerts.ClearAll();
	for (i = 0; i < patches; ++i)
	{
		if (!delPatches[i])
		{
			Patch& p = patch->patches[i];
			for (int j = 0; j < p.type; ++j)
			{
				usedVerts.Set(p.v[j]);
			}
		}
	}
	for (i = 0; i < verts; ++i)
	{
		if (!usedVerts[i])
			delVerts.Set(i);
	}

	// If we have texture vertices, handle them, too
	for (int chan = 0; chan < patch->getNumMaps(); ++chan)
	{
		int tverts = patch->numTVerts[chan];
		if (tverts && patch->tvPatches[chan])
		{
			BitArray delTVerts(tverts);
			delTVerts.SetAll();
			for (i = 0; i < patches; ++i)
			{
				if (!delPatches[i])
				{
					Patch& p = patch->patches[i];
					TVPatch& tp = patch->tvPatches[chan][i];
					for (int j = 0; j < p.type; ++j)
						delTVerts.Clear(tp.tv[j]);
				}
			}
			// Got the list of tverts to delete -- now delete 'em
			// Build a table of redirected texture vertex indices
			int newTVerts = tverts - delTVerts.NumberSet();
			IntTab tVertIndex;
			tVertIndex.SetCount(tverts);
			UVVert *newTVertArray = new UVVert[newTVerts];
			dest = 0;
			for (i = 0; i < tverts; ++i)
			{
				if (!delTVerts[i])
				{
					newTVertArray[dest] = patch->tVerts[chan][i];
					tVertIndex[i] = dest++;
				}
			}
			delete[] patch->tVerts[chan];
#if MAX_RELEASE <= 3100
			patch->tVerts[chan] = newTVertArray;
#else
			*(patch->tVerts[chan]) = *newTVertArray;
#endif
			patch->numTVerts[chan] = newTVerts;
			// Now, copy the untagged texture patches to a new array
			// While you're at it, redirect the vertex indices
			int newTVPatches = patches - delPatches.NumberSet();
			TVPatch *newArray = new TVPatch[newTVPatches];
			dest = 0;
			for (i = 0; i < patches; ++i)
			{
				if (!delPatches[i])
				{
					Patch& p = patch->patches[i];
					TVPatch& tp = newArray[dest++];
					tp = patch->tvPatches[chan][i];
					for (int j = 0; j < p.type; ++j)
						tp.tv[j] = tVertIndex[tp.tv[j]];
				}
			}
			delete[] patch->tvPatches[chan];
			patch->tvPatches[chan] = newArray;;
		}
	}

	// Build a table of redirected vector indices
	IntTab vecIndex;
	vecIndex.SetCount(vecs);
	int newVectors = vecs - delVectors.NumberSet();
	PatchVec *newVecArray = new PatchVec[newVectors];
	dest = 0;
	for (i = 0; i < vecs; ++i)
	{
		if (!delVectors[i])
		{
			newVecArray[dest] = patch->vecs[i];
			vecIndex[i] = dest++;
		}
		else
			vecIndex[i] = -1;
	}
	delete[] patch->vecs;
	patch->vecs = newVecArray;
	patch->numVecs = newVectors;

	// Build a table of redirected vertex indices
	int newVerts = verts - delVerts.NumberSet();
	IntTab vertIndex;
	vertIndex.SetCount(verts);
	PatchVert *newVertArray = new PatchVert[newVerts];
	BitArray newVertSel(newVerts);
	newVertSel.ClearAll();
	dest = 0;
	for (i = 0; i < verts; ++i)
	{
		if (!delVerts[i])
		{
			newVertArray[dest] = patch->verts[i];
			newVertSel.Set(dest, patch->vertSel[i]);
			// redirect & adjust attached vector list
			PatchVert& v = newVertArray[dest];
			for (int j = 0; j < v.vectors.Count(); ++j)
			{
				v.vectors[j] = vecIndex[v.vectors[j]];
				if (v.vectors[j] < 0)
				{
					v.vectors.Delete(j, 1);
					j--;	// realign index
				}
			}
			vertIndex[i] = dest++;
		}
	}
	delete[] patch->verts;
	patch->verts = newVertArray;
	patch->numVerts = newVerts;
	patch->vertSel = newVertSel;

	// Now, copy the untagged patches to a new array
	// While you're at it, redirect the vertex and vector indices
	int newPatches = patches - delPatches.NumberSet();
	Patch *newArray = new Patch[newPatches];
	BitArray newPatchSel(newPatches);
	newPatchSel.ClearAll();
	dest = 0;
	for (i = 0; i < patches; ++i)
	{
		if (!delPatches[i])
		{
			newArray[dest] = patch->patches[i];
			Patch& p = newArray[dest];
			int j;
			for (j = 0; j < p.type; ++j)
				p.v[j] = vertIndex[p.v[j]];
			for (j = 0; j <(p.type * 2); ++j)
				p.vec[j] = vecIndex[p.vec[j]];
			for (j = 0; j < p.type; ++j)
				p.interior[j] = vecIndex[p.interior[j]];
			newPatchSel.Set(dest++, patch->patchSel[i]);
		}
	}

	// Rebuild info in rpatch
	rpatch->DeleteAndSweep (delVerts, delPatches, *patch);

	delete[] patch->patches;
	patch->patches = newArray;;
	patch->numPatches = newPatches;
	patch->patchSel.SetSize(newPatches, TRUE);
	patch->patchSel = newPatchSel;
	patch->buildLinkages();
}