const Foam::labelgpuList& Foam::lduAddressing::patchSortStartAddr(const label i) const { if (patchSortStartAddr_.size() != nPatches()) { calcPatchSortStart(); } return patchSortStartAddr_[i]; }
void Foam::lduAddressing::calcPatchSort() const { if (patchSortAddr_.size() == nPatches()) { FatalErrorIn("lduAddressing::calcPatchSort() const") << "patch sort already calculated" << abort(FatalError); } patchSortAddr_.setSize(nPatches()); patchSortCells_.setSize(nPatches()); for(label i = 0; i < nPatches(); i++) { if( ! patchAvailable(i)) continue; const labelgpuList& nbr = patchAddr(i); labelgpuList* sortPtr_ = new labelgpuList(nbr.size(), -1); patchSortAddr_.set(i,sortPtr_); labelgpuList& lst = *sortPtr_; labelgpuList nbrTmp(nbr); thrust::counting_iterator<label> first(0); thrust::copy ( first, first+nbr.size(), lst.begin() ); thrust::stable_sort_by_key ( nbrTmp.begin(), nbrTmp.end(), lst.begin() ); labelgpuList* cellsSortPtr= new labelgpuList(nbr.size()); patchSortCells_.set(i,cellsSortPtr); labelgpuList& cellsSort = *cellsSortPtr; thrust::copy ( thrust::make_permutation_iterator ( nbr.begin(), lst.begin() ), thrust::make_permutation_iterator ( nbr.begin(), lst.end() ), cellsSort.begin() ); cellsSort.setSize ( thrust::unique(cellsSort.begin(),cellsSort.end()) - cellsSort.begin() ); } }
// ----------------------------------------------------------------------------- // Checks all texture definitions for problems and alerts the user if any are // found. Returns true if any problems were found, false otherwise // ----------------------------------------------------------------------------- bool TextureXEditor::checkTextures() { wxString problems = wxEmptyString; // Go through all texturex lists for (auto& texture_editor : texture_editors_) { // Go through all textures for (unsigned t = 0; t < texture_editor->txList().size(); t++) { // Get texture auto tex = texture_editor->txList().texture(t); // Check its patches are all valid if (tex->isExtended()) { // Extended texture, check if each patch exists in any open archive (or as a composite texture) for (unsigned p = 0; p < tex->nPatches(); p++) { auto pentry = App::resources().getPatchEntry(tex->patch(p)->name()); auto fentry = App::resources().getFlatEntry(tex->patch(p)->name()); auto ptex = App::resources().getTexture(tex->patch(p)->name()); if (!pentry && !fentry && !ptex) problems += wxString::Format( "Texture %s contains invalid/unknown patch %s\n", tex->name(), tex->patch(p)->name()); } } else { // Regular texture, check the patch table for (unsigned p = 0; p < tex->nPatches(); p++) { if (patch_table_.patchIndex(tex->patch(p)->name()) == -1) problems += wxString::Format( "Texture %s contains invalid/unknown patch %s\n", tex->name(), tex->patch(p)->name()); } } } } // Go through patch table for (unsigned a = 0; a < patch_table_.nPatches(); a++) { // Check patch entry is valid auto& patch = patch_table_.patch(a); auto entry = App::resources().getPatchEntry(patch.name, "patches", archive_); if (!entry) { problems += wxString::Format("Patch %s cannot be found in any open archive\n", patch.name); } else { // Check patch entry type if (entry->type() == EntryType::unknownType()) EntryType::detectEntryType(entry); auto type = entry->type(); if (!type->extraProps().propertyExists("patch")) problems += wxString::Format( "Patch %s is of type \"%s\", which is not a valid gfx format for patches. " "Convert it to either Doom Gfx or PNG\n", patch.name, type->name()); } } // Display a message box with any problems found if (!problems.IsEmpty()) { ExtMessageDialog dlg(this, "Problems Found"); dlg.setMessage("The following problems were found:"); dlg.setExt(problems); dlg.ShowModal(); return true; } else return false; }
void Foam::lduAddressing::calcPatchSortStart() const { if (patchSortStartAddr_.size() == nPatches()) { FatalErrorIn("lduAddressing::calcLosortStart() const") << "losort start already calculated" << abort(FatalError); } patchSortStartAddr_.setSize(nPatches()); for(label i = 0; i < nPatches(); i++) { if( ! patchAvailable(i)) continue; const labelgpuList& nbr = patchAddr(i); const labelgpuList& lsrt = patchSortAddr(i); labelgpuList* patchSortStartPtr_ = new labelgpuList(nbr.size() + 1, nbr.size()); patchSortStartAddr_.set(i,patchSortStartPtr_); labelgpuList& lsrtStart = *patchSortStartPtr_; labelgpuList ones(nbr.size(),1); labelgpuList tmpCell(nbr.size()); labelgpuList tmpSum(nbr.size()); labelgpuList nbrSort(nbr.size()); thrust::copy ( thrust::make_permutation_iterator ( nbr.begin(), lsrt.begin() ), thrust::make_permutation_iterator ( nbr.begin(), lsrt.end() ), nbrSort.begin() ); thrust::reduce_by_key ( nbrSort.begin(), nbrSort.end(), ones.begin(), tmpCell.begin(), tmpSum.begin() ); thrust::exclusive_scan ( tmpSum.begin(), tmpSum.end(), lsrtStart.begin() ); } }
// ----------------------------------------------------------------------------- // Writes the texture list in TEXTUREX format to [texturex], using [patch_table] // for patch information. // Returns true on success, false otherwise // ----------------------------------------------------------------------------- bool TextureXList::writeTEXTUREXData(ArchiveEntry* texturex, const PatchTable& patch_table) { // Check entry was given if (!texturex) return false; if (texturex->isLocked()) return false; Log::info("Writing " + textureXFormatString() + " format TEXTUREx entry"); /* Total size of a TEXTUREx lump, in bytes: Header: 4 + (4 * numtextures) Textures: 22 * numtextures (normal format) 14 * numtextures (nameless format) 18 * numtextures (Strife 1.1 format) Patches: 10 * sum of patchcounts (normal and nameless formats) 6 * sum of patchcounts (Strife 1.1 format) */ size_t numpatchrefs = 0; size_t numtextures = textures_.size(); for (size_t i = 0; i < numtextures; ++i) { numpatchrefs += textures_[i]->nPatches(); } Log::info("{} patch references in {} textures", numpatchrefs, numtextures); size_t datasize = 0; size_t headersize = 4 + (4 * numtextures); switch (txformat_) { case Format::Normal: datasize = 4 + (26 * numtextures) + (10 * numpatchrefs); break; case Format::Nameless: datasize = 4 + (18 * numtextures) + (10 * numpatchrefs); break; case Format::Strife11: datasize = 4 + (22 * numtextures) + (6 * numpatchrefs); break; // Some compilers insist on having default cases. default: return false; } MemChunk txdata(datasize); vector<int32_t> offsets(numtextures); int32_t foo = wxINT32_SWAP_ON_BE((signed)numtextures); // Write header txdata.seek(0, SEEK_SET); SAFEFUNC(txdata.write(&foo, 4)); // Go to beginning of texture definitions SAFEFUNC(txdata.seek(4 + (numtextures * 4), SEEK_SET)); // Write texture entries for (size_t i = 0; i < numtextures; ++i) { // Get texture to write auto tex = textures_[i].get(); // Set offset offsets[i] = (signed)txdata.currentPos(); // Write texture entry switch (txformat_) { case Format::Normal: { // Create 'normal' doom format texture definition FullTexDef txdef; memset(txdef.name, 0, 8); // Set texture name to all 0's (to ensure compatibility with XWE) strncpy(txdef.name, tex->name().data(), tex->name().size()); for (auto& c : txdef.name) c = toupper(c); txdef.flags = 0; txdef.scale[0] = (tex->scaleX() * 8); txdef.scale[1] = (tex->scaleY() * 8); txdef.width = tex->width(); txdef.height = tex->height(); txdef.columndir[0] = 0; txdef.columndir[1] = 0; txdef.patchcount = tex->nPatches(); // Check for WorldPanning flag if (tex->world_panning_) txdef.flags |= Flags::WorldPanning; // Write texture definition SAFEFUNC(txdata.write(&txdef, 22)); break; } case Format::Nameless: { // Create nameless texture definition NamelessTexDef txdef; txdef.flags = 0; txdef.scale[0] = (tex->scaleX() * 8); txdef.scale[1] = (tex->scaleY() * 8); txdef.width = tex->width(); txdef.height = tex->height(); txdef.columndir[0] = 0; txdef.columndir[1] = 0; txdef.patchcount = tex->nPatches(); // Write texture definition SAFEFUNC(txdata.write(&txdef, 8)); break; } case Format::Strife11: { // Create strife format texture definition StrifeTexDef txdef; memset(txdef.name, 0, 8); // Set texture name to all 0's (to ensure compatibility with XWE) strncpy(txdef.name, tex->name().data(), tex->name().size()); for (auto& c : txdef.name) c = toupper(c); txdef.flags = 0; txdef.scale[0] = (tex->scaleX() * 8); txdef.scale[1] = (tex->scaleY() * 8); txdef.width = tex->width(); txdef.height = tex->height(); txdef.patchcount = tex->nPatches(); // Check for WorldPanning flag if (tex->world_panning_) txdef.flags |= Flags::WorldPanning; // Write texture definition SAFEFUNC(txdata.write(&txdef, 18)); break; } default: return false; } // Write patch references for (size_t k = 0; k < tex->nPatches(); ++k) { // Get patch to write auto patch = tex->patch(k); // Create patch definition Patch pdef; pdef.left = patch->xOffset(); pdef.top = patch->yOffset(); // Check for 'invalid' patch if (StrUtil::startsWith(patch->name(), "INVPATCH")) { // Get raw patch index from name std::string_view number = patch->name(); number.remove_prefix(8); pdef.patch = StrUtil::asInt(number); } else pdef.patch = patch_table.patchIndex( patch->name()); // Note this will be -1 if the patch doesn't exist in the patch table. This // should never happen with the texture editor, though. // Write common data SAFEFUNC(txdata.write(&pdef, 6)); // In non-Strife formats, there's some added rubbish if (txformat_ != Format::Strife11) { foo = 0; SAFEFUNC(txdata.write(&foo, 4)); } } } // Write offsets SAFEFUNC(txdata.seek(4, SEEK_SET)); SAFEFUNC(txdata.write(offsets.data(), 4 * numtextures)); // Write data to the TEXTUREx entry texturex->importMemChunk(txdata); // Update entry type EntryType::detectEntryType(texturex); return true; }