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]]); } }
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); } } }
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(); }