diff options
| author | Bryan Galdrikian <[email protected]> | 2017-02-21 12:07:59 -0800 |
|---|---|---|
| committer | Bryan Galdrikian <[email protected]> | 2017-02-21 12:07:59 -0800 |
| commit | 446ce137c6823ba9eff273bdafdaf266287c7c98 (patch) | |
| tree | d20aab3e2ed08d7b3ca71c2f40db6a93ea00c459 /NvBlast/tools/AuthoringTool/src | |
| download | blast-1.0.0-beta.tar.xz blast-1.0.0-beta.zip | |
first commitv1.0.0-beta
Diffstat (limited to 'NvBlast/tools/AuthoringTool/src')
| -rw-r--r-- | NvBlast/tools/AuthoringTool/src/AuthoringTool.cpp | 403 | ||||
| -rw-r--r-- | NvBlast/tools/AuthoringTool/src/FractureProcessor.cpp | 264 | ||||
| -rw-r--r-- | NvBlast/tools/AuthoringTool/src/FractureProcessor.h | 64 | ||||
| -rw-r--r-- | NvBlast/tools/AuthoringTool/src/SimpleRandomGenerator.h | 27 |
4 files changed, 758 insertions, 0 deletions
diff --git a/NvBlast/tools/AuthoringTool/src/AuthoringTool.cpp b/NvBlast/tools/AuthoringTool/src/AuthoringTool.cpp new file mode 100644 index 0000000..4898d3b --- /dev/null +++ b/NvBlast/tools/AuthoringTool/src/AuthoringTool.cpp @@ -0,0 +1,403 @@ +#include "PxPhysicsAPI.h" +#include "PxAllocatorCallback.h" +#include "PxErrorCallback.h" +#include "PsFileBuffer.h" +#include "NvBlast.h" +#include "NvBlastExtAuthoringCollisionBuilder.h" +#include "NvBlastExtSerializationLLInterface.h" +#include "NvBlastExtSerializationInterface.h" +#include "NvBlastExtAuthoringBondGenerator.h" +#include "NvBlastExtAuthoringFractureTool.h" +#include "NvBlastExtAuthoringMesh.h" +#include "SimpleRandomGenerator.h" +#include "FbxFileReader.h" +#include "ObjFileReader.h" +#include "FractureProcessor.h" +#include "FbxFileWriter.h" +#include "ObjFileWriter.h" +#include "BlastDataExporter.h" +#include <string> +#include <iostream> +#include <vector> +#include <cctype> +#include <fstream> +#include <iosfwd> +#include <Windows.h> +#include "tclap/CmdLine.h" + +using physx::PxVec3; +using physx::PxVec2; + +#define DEFAULT_ASSET_NAME "AuthoringTest" + + +using namespace Nv::Blast; + +struct TCLAPint3 +{ + int32_t x, y, z; + TCLAPint3(int32_t x, int32_t y, int32_t z) :x(x), y(y), z(z){}; + TCLAPint3() :x(0), y(0), z(0){}; + TCLAPint3& operator=(const std::string &inp) + { + std::istringstream stream(inp); + if (!(stream >> x >> y >> z)) + throw TCLAP::ArgParseException(inp + " is not int3"); + return *this; + } +}; + +namespace TCLAP { + template<> + struct ArgTraits<TCLAPint3> { + typedef StringLike ValueCategory; + }; +} + +bool isDirectoryExist(std::string path) +{ + DWORD attributes = GetFileAttributesA(path.c_str()); + if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) + { + return true; + } + return false; +} + +bool mkDirRecursively(std::string path) +{ + if (isDirectoryExist(path)) + { + return true; + } + auto indx = path.find_first_of("\\/"); + while (indx != std::string::npos) + { + std::string subfolder = path.substr(0, indx); + CreateDirectory(subfolder.c_str(), NULL); + indx = path.find_first_of("\\/", indx + 1); + } + return isDirectoryExist(path); +} + +int main(int argc, const char* const* argv) +{ + // setup cmd line + TCLAP::CmdLine cmd("Blast SDK: Authoring Tool", ' ', "0.1"); + + TCLAP::UnlabeledValueArg<std::string> infileArg("file", "File to load", true, "", "infile"); + cmd.add(infileArg); + + TCLAP::UnlabeledValueArg<std::string> outAssetName("outAssetName", "Output asset name", true, DEFAULT_ASSET_NAME, "output asset name"); + cmd.add(outAssetName); + + TCLAP::ValueArg<std::string> outDirArg("", "outputDir", "Output directory", false, ".", "by default directory of the input file"); + cmd.add(outDirArg); + + // The output modes + //NOTE: Fun TCLAP quirk here - if you set the default to true and specify this switch on the command line, the value will be false! + TCLAP::SwitchArg bpxaOutputArg("", "bpxa", "Output ExtPxAsset to the output directory (ext: bpxa)", false); + cmd.add(bpxaOutputArg); + + TCLAP::SwitchArg tkOutputArg("", "tk", "Output TkAsset to the output directory (ext: tkasset)", false); + cmd.add(tkOutputArg); + + TCLAP::SwitchArg llOutputArg("", "ll", "Output LL Blast asset to the output directory (ext: llasset)", false); + cmd.add(llOutputArg); + + TCLAP::SwitchArg ue4OutputArg("", "ue4", "Output FBX with UE4 coordinate system", false); + cmd.add(ue4OutputArg); + + TCLAP::SwitchArg fbxAsciiArg("", "fbxascii", "Output FBX as an ascii file (defaults to binary output)", false); + cmd.add(fbxAsciiArg); + + TCLAP::SwitchArg objOutputArg("", "obj", "Output a OBJ mesh to the output directory", false); + cmd.add(objOutputArg); + + TCLAP::SwitchArg fbxOutputArg("", "fbx", "Output a FBX mesh to the output directory", false); + cmd.add(fbxOutputArg); + + TCLAP::SwitchArg protoSer("", "proto", "Serialize Blast data with CapnProto", false); + cmd.add(protoSer); + + TCLAP::SwitchArg blockSer("", "block", "Serialize Blast data as block of memory", false); + cmd.add(blockSer); + + + + + TCLAP::ValueArg<unsigned char> fracturingMode("", "mode", "Fracturing mode", false, 'v', "v - voronoi, c - clustered voronoi, s - slicing."); + cmd.add(fracturingMode); + TCLAP::ValueArg<uint32_t> cellsCount("", "cells", "Voronoi cells count", false, 5, "by default 5"); + cmd.add(cellsCount); + TCLAP::ValueArg<uint32_t> clusterCount("", "clusters", "Uniform Voronoi cluster count", false, 5, "by default 5"); + cmd.add(clusterCount); + TCLAP::ValueArg<float> clusterRad("", "radius", "Clustered Voronoi cluster radius", false, 1.0f, "by default 1.0"); + cmd.add(clusterRad); + + TCLAP::ValueArg<TCLAPint3> slicingNumber("", "slices", "Number of slices per direction", false, TCLAPint3(1, 1, 1), "by default 1 1 1"); + cmd.add(slicingNumber); + + TCLAP::ValueArg<float> angleVariation("", "avar", "Slicing angle variation", false, 0.0, "by default 0.0"); + cmd.add(angleVariation); + + TCLAP::ValueArg<float> offsetVariation("", "ovar", "Slicing offset variation", false, 0.0, "by default 0.0"); + cmd.add(offsetVariation); + + try + { + // parse cmd input + cmd.parse(argc, argv); + } + catch (TCLAP::ArgException &e) // catch any exceptions + { + std::cout << "error: " << e.error() << " for arg " << e.argId() << std::endl; + return -1; + } + + // get cmd parse results + std::string infile = infileArg.getValue(); + + std::string outDir; + + + if (outDirArg.isSet()) + { + outDir = outDirArg.getValue(); + std::string temp = outDir + '/'; + if (!isDirectoryExist(outDir.data())) + { + std::cout << "Output directory doesn't exist. It will be created." << std::endl; + if (!mkDirRecursively(temp.data())) + { + std::cout << "Directory creation failed!" << std::endl; + return -1; + } + } + } + else + { + auto idx = infile.find_last_of("/\\"); + if (idx == 0 || idx == std::string::npos) + { + outDir = "."; + } + else + { + outDir = infile.substr(0, idx); + } + } + std::string assetName = outAssetName.getValue(); + + // Determine whether to use the obj or fbx loader + + auto idx = infile.rfind('.'); + std::string extension; + + + if (idx != std::string::npos) + { + extension = infile.substr(idx + 1); + std::transform(extension.begin(), extension.end(), extension.begin(), std::toupper); + } + else + { + std::cout << "Can't determine extension (and thus, loader) of input file. " << infile << std::endl; + return -1; + } + + bool bOutputBPXA = bpxaOutputArg.getValue(); + bool bOutputTK = tkOutputArg.getValue(); + bool bOutputLL = llOutputArg.getValue(); + + bool bUE4CoordSystem = ue4OutputArg.getValue(); + bool bOutputFBXAscii = fbxAsciiArg.getValue(); + + bool bOutputObjFile = objOutputArg.isSet(); + bool bOutputFbxFile = fbxOutputArg.isSet(); + + bool bOutputProtobufSer = protoSer.isSet(); + bool bOutputBlockSer = blockSer.isSet(); + + + // Did we specify no output formats? + if (!bpxaOutputArg.isSet() && !tkOutputArg.isSet() && !llOutputArg.isSet()) + { + std::cout << "Didn't specify an output format on the command line, so defaulting to outputting BPXA" << std::endl; + bOutputBPXA = true; + } + // Did we specify no geometry output formats? + if (!bOutputObjFile && !bOutputFbxFile) + { + std::cout << "Didn't specify an output geometry format on the command line, so defaulting to outputting .FBX" << std::endl; + bOutputFbxFile = true; + } + // Did we specify no serialization type? + if (!bOutputBlockSer && !bOutputProtobufSer) + { + std::cout << "Didn't specify an serialization type on the command line, so defaulting to block serialization type" << std::endl; + bOutputBlockSer = true; + } + + std::shared_ptr<IMeshFileReader> fileReader; + + if (extension.compare("FBX")==0) + { + fileReader = std::make_shared<FbxFileReader>(); + } + else if (extension.compare("OBJ")==0) + { + fileReader = std::make_shared<ObjFileReader>(); + } + else + { + std::cout << "Unsupported file extension " << extension << std::endl; + return -1; + } + + fileReader->setConvertToUE4(bUE4CoordSystem); + + // Load the asset + std::shared_ptr<Mesh> loadedMesh = fileReader->loadFromFile(infile); + + if (loadedMesh == nullptr) + { + std::cout << "Failed to load mesh " << infile << std::endl; + return -1; + } + + // Send it to the fracture processor + FractureProcessor processor; + FractureSettings settings; + settings.mode = fracturingMode.getValue(); + settings.cellsCount = cellsCount.getValue(); + settings.clusterCount = clusterCount.getValue(); + settings.slicingX = slicingNumber.getValue().x; + settings.slicingY = slicingNumber.getValue().y; + settings.slicingZ = slicingNumber.getValue().z; + settings.angleVariation = angleVariation.getValue(); + settings.offsetVariation = offsetVariation.getValue(); + settings.clusterRadius = clusterRad.getValue(); + + std::shared_ptr<FractureResult> result = processor.fractureMesh(loadedMesh, settings); + + // Output the results + // NOTE: Writing to FBX by default. + std::shared_ptr<IMeshFileWriter> fileWriter; + + + auto assetLL = result->resultPhysicsAsset->getTkAsset().getAssetLL(); + + + if (bOutputObjFile) + { + if (bUE4CoordSystem) + { + std::cout << "OBJ output doesn't support UE4 coordinate conversion." << std::endl; + } + fileWriter = std::make_shared<ObjFileWriter>(); + bool writeResult = fileWriter->saveToFile(assetLL, result->resultGeometry, assetName, outDir); + if (!writeResult) + { + std::cerr << "Can't write geometry to OBJ file." << std::endl; + return -1; + } + } + if (bOutputFbxFile) + { + fileWriter = std::make_shared<FbxFileWriter>(); + fileWriter->setConvertToUE4(bUE4CoordSystem); + { + auto fbxWriter = static_cast<FbxFileWriter *>(fileWriter.get()); + fbxWriter->bOutputFBXAscii = bOutputFBXAscii; + } + + bool writeResult = fileWriter->saveToFile(assetLL, result->resultGeometry, assetName, outDir); + if (!writeResult) + { + std::cerr << "Can't write geometry to FBX file." << std::endl; + return -1; + } + } + + if (bOutputProtobufSer) + { + if (bOutputBPXA) + { + std::ostringstream outBlastFilePathStream; + outBlastFilePathStream << outDir << "/" << assetName << ".pbpxa"; + std::string outBlastFilePath = outBlastFilePathStream.str(); + + std::ofstream myFile(outBlastFilePath, std::ios::out | std::ios::binary); + + setPhysXSDK(processor.getPhysics()); + + serializeExtPxAssetIntoStream(result->resultPhysicsAsset.get(), myFile); + + myFile.flush(); + + std::cout << "Wrote ExtPxAsset to " << outBlastFilePath << std::endl; + } + + if (bOutputTK) + { + std::ostringstream outBlastFilePathStream; + outBlastFilePathStream << outDir << "/" << assetName << ".ptkasset"; + std::string outBlastFilePath = outBlastFilePathStream.str(); + + std::ofstream myFile(outBlastFilePath, std::ios::out | std::ios::binary); + + serializeTkAssetIntoStream(&result->resultPhysicsAsset->getTkAsset(), myFile); + + myFile.flush(); + + std::cout << "Wrote TkAsset to " << outBlastFilePath << std::endl; + } + + if (bOutputLL) + { + std::ostringstream outBlastFilePathStream; + outBlastFilePathStream << outDir << "/" << assetName << ".pllasset"; + std::string outBlastFilePath = outBlastFilePathStream.str(); + + std::ofstream myFile(outBlastFilePath, std::ios::out | std::ios::binary); + + serializeAssetIntoStream(result->resultPhysicsAsset->getTkAsset().getAssetLL(), myFile); + + myFile.flush(); + + std::cout << "Wrote NvBlastAsset to " << outBlastFilePath << std::endl; + } + } + + if (bOutputBlockSer) + { + BlastDataExporter blExpr(NvBlastTkFrameworkGet(), processor.getCooking(), NvBlastTkFrameworkGet()->getLogFn()); + if (bOutputLL) + { + std::ostringstream outBlastFilePathStream; + outBlastFilePathStream << outDir << "/" << assetName << ".llasset"; + std::string outBlastFilePath = outBlastFilePathStream.str(); + blExpr.saveBlastLLAsset(outBlastFilePath, result->resultPhysicsAsset->getTkAsset().getAssetLL()); + std::cout << "Wrote NvBlastAsset to " << outBlastFilePath << std::endl; + } + if (bOutputTK) + { + std::ostringstream outBlastFilePathStream; + outBlastFilePathStream << outDir << "/" << assetName << ".tkasset"; + std::string outBlastFilePath = outBlastFilePathStream.str(); + blExpr.saveBlastTkAsset(outBlastFilePath, &result->resultPhysicsAsset->getTkAsset()); + std::cout << "Wrote TkAsset to " << outBlastFilePath << std::endl; + } + if (bOutputBPXA) + { + std::ostringstream outBlastFilePathStream; + outBlastFilePathStream << outDir << "/" << assetName << ".bpxa"; + std::string outBlastFilePath = outBlastFilePathStream.str(); + blExpr.saveBlastExtAsset(outBlastFilePath, result->resultPhysicsAsset.get()); + std::cout << "Wrote ExtPxAsset to " << outBlastFilePath << std::endl; + } + } + + return 0; +} diff --git a/NvBlast/tools/AuthoringTool/src/FractureProcessor.cpp b/NvBlast/tools/AuthoringTool/src/FractureProcessor.cpp new file mode 100644 index 0000000..75307d9 --- /dev/null +++ b/NvBlast/tools/AuthoringTool/src/FractureProcessor.cpp @@ -0,0 +1,264 @@ +#include "FractureProcessor.h" +#include "NvBlastExtAuthoringCollisionBuilder.h" +#include <iostream> +#include "PxPhysicsAPI.h" +#include "NvBlastTkFramework.h" +#include "NvBlastExtAuthoringFractureTool.h" +#include "SimpleRandomGenerator.h" +#include "NvBlastExtAuthoringBondGenerator.h" +#include "NvBlastTypes.h" +#include "NvBlastIndexFns.h" +#include "NvBlast.h" +#include <ctime> +using namespace Nv::Blast; + +void loggingCallback(int type, const char* msg, const char* file, int line) +{ + (void)type; + + std::cout << msg << " FILE:" << file << " Line: " << line << "\n"; +} + + +FractureProcessor::FractureProcessor() +{ + initPhysX(); + + Nv::Blast::TkFrameworkDesc frameworkDesc = + { + &g_errorCallback, + &g_allocator + }; + + framework = NvBlastTkFrameworkCreate(frameworkDesc); + if (framework == nullptr) + { + std::cout << "Failed to create TkFramework" << std::endl; + return; + } +} + +FractureProcessor::~FractureProcessor() +{ + releasePhysX(); + + if (framework != nullptr) + { + framework->release(); + } +} + +void FractureProcessor::buildPhysicsChunks(const std::vector<std::vector<Nv::Blast::Triangle>>& chunkGeometry, std::vector<Nv::Blast::ExtPxAssetDesc::ChunkDesc>& outPhysicsChunks, std::vector<Nv::Blast::ExtPxAssetDesc::SubchunkDesc>& outPhysicsSubchunks) +{ + Nv::Blast::ConvexMeshBuilder collisionBuilder(cooking, &physics->getPhysicsInsertionCallback()); + + outPhysicsChunks.resize(chunkGeometry.size()); + outPhysicsSubchunks.resize(chunkGeometry.size()); + + for (uint32_t i = 0; i < chunkGeometry.size(); ++i) + { + std::vector<physx::PxVec3> vertices; + for (uint32_t p = 0; p < chunkGeometry[i].size(); ++p) + { + vertices.push_back(chunkGeometry[i][p].a.p); + vertices.push_back(chunkGeometry[i][p].b.p); + vertices.push_back(chunkGeometry[i][p].c.p); + } + outPhysicsSubchunks[i].transform = physx::PxTransform(physx::PxIdentity); + outPhysicsSubchunks[i].geometry = physx::PxConvexMeshGeometry(collisionBuilder.buildConvexMesh(vertices)); + outPhysicsChunks[i].isStatic = false; + outPhysicsChunks[i].subchunkCount = 1; + outPhysicsChunks[i].subchunks = &outPhysicsSubchunks[i]; + } + +} + +std::shared_ptr<FractureResult> FractureProcessor::fractureMesh(std::shared_ptr<Nv::Blast::Mesh> sourceMesh, const FractureSettings &settings) +{ + // Create FractureTool + + std::cout << "Fracture tool initialization" << std::endl; + + std::vector<NvBlastChunkDesc> chunkDesc; + std::vector<NvBlastBondDesc> bondDescs; + std::vector<std::vector<Nv::Blast::Triangle> > chunkMeshes; + std::vector<bool> isSupport; + + Nv::Blast::FractureTool fTool(loggingCallback); + + fTool.setSourceMesh(sourceMesh.get()); + SimpleRandomGenerator rnd; + rnd.seed((int32_t)time(nullptr)); // Keep the same seed to have reproducible results. + + std::cout << "Fracturing..." << std::endl; + VoronoiSitesGenerator stGenerator(sourceMesh.get(), &rnd); + switch (settings.mode) + { + case 'c': + stGenerator.clusteredSitesGeneration(settings.clusterCount, settings.cellsCount, settings.clusterRadius); + fTool.voronoiFracturing(0, stGenerator.getVoronoiSites(), false); + break; + case 's': + { + SlicingConfiguration slConfig; + slConfig.x_slices = settings.slicingX; + slConfig.y_slices = settings.slicingY; + slConfig.z_slices = settings.slicingZ; + slConfig.angle_variations = settings.angleVariation; + slConfig.offset_variations = settings.offsetVariation; + fTool.slicing(0, slConfig, false, &rnd); + break; + } + case 'v': + stGenerator.uniformlyGenerateSitesInMesh(settings.cellsCount); + fTool.voronoiFracturing(0, stGenerator.getVoronoiSites(), false); + break; + default: + std::cout << "Not supported mode" << std::endl; + return nullptr; + } + std::cout << "Creating geometry" << std::endl; + fTool.finalizeFracturing(); + + chunkMeshes.resize(fTool.getChunkList().size()); + isSupport.resize(fTool.getChunkList().size()); + for (uint32_t i = 0; i < fTool.getChunkList().size(); ++i) + { + fTool.getBaseMesh(i, chunkMeshes[i]); + isSupport[i] = fTool.getChunkList()[i].isLeaf; + + } + + + BlastBondGenerator bondGenerator(cooking, &physics->getPhysicsInsertionCallback()); + + BondGenerationConfig cnf; + cnf.bondMode = BondGenerationConfig::EXACT; + + bondGenerator.buildDescFromInternalFracture(&fTool, isSupport, bondDescs, chunkDesc); + +// const uint32_t chunkCount = static_cast<uint32_t>(chunkDesc.size()); + const uint32_t bondCount = static_cast<uint32_t>(bondDescs.size()); + if (bondCount == 0) + { + std::cout << "Can't create bonds descriptors..." << std::endl; + return nullptr; + } + + return finalizeMeshProcessing(chunkDesc, bondDescs, chunkMeshes); +} + +std::shared_ptr<FractureResult> FractureProcessor::finalizeMeshProcessing(std::vector<NvBlastChunkDesc> chunkDesc, std::vector<NvBlastBondDesc> bondDescs, std::vector<std::vector<Nv::Blast::Triangle> > chunkMeshes) +{ + const uint32_t chunkCount = static_cast<uint32_t>(chunkDesc.size()); + const uint32_t bondCount = static_cast<uint32_t>(bondDescs.size()); + + // order chunks, build map + std::vector<uint32_t> chunkReorderInvMap; + { + std::vector<uint32_t> chunkReorderMap(chunkCount); + std::vector<char> scratch(chunkCount * sizeof(NvBlastChunkDesc)); + NvBlastEnsureAssetExactSupportCoverage(chunkDesc.data(), chunkCount, scratch.data(), loggingCallback); + NvBlastBuildAssetDescChunkReorderMap(chunkReorderMap.data(), chunkDesc.data(), chunkCount, scratch.data(), loggingCallback); + NvBlastApplyAssetDescChunkReorderMapInplace(chunkDesc.data(), chunkCount, bondDescs.data(), bondCount, chunkReorderMap.data(), scratch.data(), loggingCallback); + chunkReorderInvMap.resize(chunkReorderMap.size()); + Nv::Blast::invertMap(chunkReorderInvMap.data(), chunkReorderMap.data(), static_cast<unsigned int>(chunkReorderMap.size())); + } + + std::shared_ptr<FractureResult> result = std::make_shared<FractureResult>(); + + // get result geometry + + result->resultGeometry.resize(chunkMeshes.size()); + //std::vector<std::vector<Triangle>> resultGeometry(chunkMeshes.size()); + for (uint32_t i = 0; i < chunkMeshes.size(); ++i) + { + uint32_t chunkIndex = chunkReorderInvMap[i]; + result->resultGeometry[i] = chunkMeshes[chunkIndex]; + } + + float maxX = INT32_MIN; + float maxY = INT32_MIN; + float maxZ = INT32_MIN; + + float minX = INT32_MAX; + float minY = INT32_MAX; + float minZ = INT32_MAX; + + for (uint32_t i = 0; i < bondDescs.size(); i++) + { + NvBlastBondDesc bondDesc = bondDescs[i]; + + minX = std::min(minX, bondDesc.bond.centroid[0]); + maxX = std::max(maxX, bondDesc.bond.centroid[0]); + + minY = std::min(minY, bondDesc.bond.centroid[1]); + maxY = std::max(maxY, bondDesc.bond.centroid[1]); + + minZ = std::min(minZ, bondDesc.bond.centroid[2]); + maxZ = std::max(maxZ, bondDesc.bond.centroid[2]); + } + + std::cout << "Bond bounds: " << std::endl; + std::cout << "MIN: " << minX << ", " << minY << ", " << minZ << std::endl; + std::cout << "MAX: " << maxX << ", " << maxY << ", " << maxZ << std::endl; + + // prepare physics data (convexes) + std::vector<Nv::Blast::ExtPxAssetDesc::ChunkDesc> physicsChunks(chunkCount); + std::vector<Nv::Blast::ExtPxAssetDesc::SubchunkDesc> physicsSubchunks; + buildPhysicsChunks(result->resultGeometry, physicsChunks, physicsSubchunks); + + // build and serialize ExtPhysicsAsset + Nv::Blast::ExtPxAssetDesc descriptor; + descriptor.bondCount = bondCount; + descriptor.bondDescs = bondDescs.data(); + descriptor.chunkCount = chunkCount; + descriptor.chunkDescs = chunkDesc.data(); + descriptor.bondFlags = nullptr; + descriptor.pxChunks = physicsChunks.data(); + + result->resultPhysicsAsset = std::shared_ptr<Nv::Blast::ExtPxAsset>(Nv::Blast::ExtPxAsset::create(descriptor, *framework), [=](Nv::Blast::ExtPxAsset* asset) + { + asset->release(); + }); + + std::cout << "Done" << std::endl; + + return result; +} + +bool FractureProcessor::initPhysX() +{ + foundation = PxCreateFoundation(PX_FOUNDATION_VERSION, g_allocator, g_errorCallback); + if (!foundation) + { + std::cout << "Can't init PhysX foundation" << std::endl; + return false; + } + physx::PxTolerancesScale scale; + physics = PxCreatePhysics(PX_PHYSICS_VERSION, *foundation, scale, true); + if (!physics) + { + std::cout << "Can't create Physics" << std::endl; + return false; + } + physx::PxCookingParams cookingParams(scale); + cookingParams.buildGPUData = true; + cooking = PxCreateCooking(PX_PHYSICS_VERSION, physics->getFoundation(), cookingParams); + if (!cooking) + { + std::cout << "Can't create Cooking" << std::endl; + return false; + } + return true; +} + +void FractureProcessor::releasePhysX() +{ + cooking->release(); + cooking = 0; + physics->release(); + physics = 0; + foundation->release(); + foundation = 0; +} diff --git a/NvBlast/tools/AuthoringTool/src/FractureProcessor.h b/NvBlast/tools/AuthoringTool/src/FractureProcessor.h new file mode 100644 index 0000000..8b8fefe --- /dev/null +++ b/NvBlast/tools/AuthoringTool/src/FractureProcessor.h @@ -0,0 +1,64 @@ +#pragma once +#include <vector> +#include "NvBlastExtAuthoringTypes.h" +#include "PxFoundation.h" +#include "PxPhysics.h" +#include "PxCooking.h" +#include "PxDefaultAllocator.h" +#include "PxDefaultErrorCallback.h" +#include <memory> +#include "NvBlastExtAuthoringMesh.h" +#include "NvBlastExtAuthoringBondGenerator.h" +#include "NvBlastTypes.h" +#include "NvBlastExtPxAsset.h" + +struct FractureResult +{ + std::vector<std::vector<Nv::Blast::Triangle>> resultGeometry; + std::shared_ptr<Nv::Blast::ExtPxAsset> resultPhysicsAsset; +}; + +struct FractureSettings +{ + unsigned char mode; + uint32_t cellsCount; + uint32_t clusterCount; + float clusterRadius; + int32_t slicingX; + int32_t slicingY; + int32_t slicingZ; + float angleVariation; + float offsetVariation; +}; + +class FractureProcessor +{ +public: + FractureProcessor(); + ~FractureProcessor(); + + + std::shared_ptr<FractureResult> fractureMesh(std::shared_ptr<Nv::Blast::Mesh> sourceMesh, const FractureSettings &settings); + + + physx::PxPhysics* getPhysics() { return physics; } + physx::PxCooking* getCooking() { return cooking; } +private: + physx::PxFoundation* foundation = nullptr; + physx::PxPhysics* physics = nullptr; + physx::PxCooking* cooking = nullptr; + + Nv::Blast::TkFramework* framework = nullptr; + + physx::PxDefaultAllocator g_allocator; + physx::PxDefaultErrorCallback g_errorCallback; + + + void buildPhysicsChunks(const std::vector<std::vector<Nv::Blast::Triangle>>& chunkGeometry, std::vector<Nv::Blast::ExtPxAssetDesc::ChunkDesc>& outPhysicsChunks, + std::vector<Nv::Blast::ExtPxAssetDesc::SubchunkDesc>& outPhysicsSubchunks); + + std::shared_ptr<FractureResult> finalizeMeshProcessing(std::vector<NvBlastChunkDesc> chunkDesc, std::vector<NvBlastBondDesc> bondDescs, std::vector<std::vector<Nv::Blast::Triangle> > chunkMeshes); + + bool initPhysX(); + void releasePhysX(); +}; diff --git a/NvBlast/tools/AuthoringTool/src/SimpleRandomGenerator.h b/NvBlast/tools/AuthoringTool/src/SimpleRandomGenerator.h new file mode 100644 index 0000000..63e2d45 --- /dev/null +++ b/NvBlast/tools/AuthoringTool/src/SimpleRandomGenerator.h @@ -0,0 +1,27 @@ +#pragma once +#include "NvBlastExtAuthoringTypes.h" + + +class SimpleRandomGenerator : public Nv::Blast::RandomGeneratorBase +{ +public: + SimpleRandomGenerator() { + remember = false; + }; + + virtual float getRandomValue() + { + float r = (float)rand(); + r = r / RAND_MAX; + return r; + } + virtual void seed(int32_t seed) + { + srand(seed); + } + + virtual ~SimpleRandomGenerator() {}; + +private: + bool remember; +};
\ No newline at end of file |