cleanup license stuff, separated voxel conversion to a function

This commit is contained in:
Harvey Fong 2025-04-05 12:30:27 -06:00
parent 087433e233
commit 9d8877f391
5 changed files with 139 additions and 250 deletions

View File

@ -18,7 +18,7 @@ workdir/
├── libplist/ ├── libplist/
├── lzfse/ ├── lzfse/
├── efsw/ ├── efsw/
└── vox2bella/ └── vmaxtui/
``` ```
# MacOS # MacOS
@ -48,9 +48,9 @@ cd efsw/build
/Applications/CMake.app/Contents/bin/cmake .. /Applications/CMake.app/Contents/bin/cmake ..
make -j4 make -j4
cd ../.. cd ../..
git clone https://github.com/oomer/vmax2bella.git git clone https://github.com/oomer/vmaxtui.git
cd vmax2bella cd vmaxtui
make make all -j4
``` ```
# Linux [NOT READY] # Linux [NOT READY]
@ -73,9 +73,9 @@ mkdir -p efsw/build
cd efsw/build cd efsw/build
cmake .. cmake ..
make -j4 make -j4
git clone https://github.com/oomer/vmax2bella.git git clone https://github.com/oomer/vmaxtui.git
cd vmax2bella cd vmaxtui
make make all -j4
``` ```
# Windows [NOT READY] # Windows [NOT READY]
@ -86,7 +86,7 @@ make
mkdir workdir mkdir workdir
git clone https://github.com/lzfse/lzfse git clone https://github.com/lzfse/lzfse
git clone https://github.com/oomer/vmax2bella.git git clone https://github.com/oomer/vmaxtui.git
cd vmax2bella cd vmaxtui
msbuild vox2bella.vcxproj /p:Configuration=release /p:Platform=x64 /p:PlatformToolset=v143 msbuild vmaxtui.vcxproj /p:Configuration=release /p:Platform=x64 /p:PlatformToolset=v143
``` ```

View File

@ -233,4 +233,27 @@ inline bool endsWith(const std::string& str, const std::string& suffix) {
return false; return false;
} }
return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0; return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
} }
/*
MIT License
Copyright (c) 2025 Harvey Fong
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

View File

@ -88,6 +88,7 @@ inline void saveHDRI() {
inline std::string initializeMyLicense() { inline std::string initializeMyLicense() {
// R"(...)" is a C++ raw string literal - allows multi-line strings with preserved formatting // R"(...)" is a C++ raw string literal - allows multi-line strings with preserved formatting
return R"( return R"(
=============================================================================
Copyright (c) 2025 Harvey Fong Copyright (c) 2025 Harvey Fong
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
@ -106,12 +107,15 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.)"; SOFTWARE.
=============================================================================
)";
} }
// Function that returns third-party license text // Function that returns third-party license text
inline std::string initializeThirdPartyLicences() { inline std::string initializeThirdPartyLicences() {
return R"( return R"(
=============================================================================
Bella SDK (Software Development Kit) Bella SDK (Software Development Kit)
Copyright Diffuse Logic SCP, all rights reserved. Copyright Diffuse Logic SCP, all rights reserved.
@ -123,8 +127,7 @@ copies of the Software.
THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ALL THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ALL
IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF MERCHANTABILITY IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF MERCHANTABILITY
ARE HEREBY DISCLAIMED.) ARE HEREBY DISCLAIMED.)
=============================================================================
===
lzfse lzfse
@ -146,16 +149,50 @@ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================
===
DayEnvironmentHDRI019_1K-TONEMAPPED.jpg from ambientCG.com, DayEnvironmentHDRI019_1K-TONEMAPPED.jpg from ambientCG.com,
licensed under the Creative Commons CC0 1.0 Universal License. licensed under the Creative Commons CC0 1.0 Universal License.
=============================================================================
===
https://github.com/libimobiledevice/libplist https://github.com/libimobiledevice/libplist
This software uses libraries from the libplist project under the LGPL version 2.1. This software uses libraries from the libplist project under the LGPL version 2.1.
=============================================================================
__ _____ _____ _____
__| | __| | | | JSON for Modern C++
| | |__ | | | | | | version 3.11.3
|_____|_____|_____|_|___| https://github.com/nlohmann/json
SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
SPDX-License-Identifier: MIT
=============================================================================
efsw
Copyright (c) 2020 Martín Lucas Golini
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com)
http://code.google.com/p/simplefilewatcher/ also MIT licensed.
)"; )";
} }
@ -1585,4 +1622,27 @@ const unsigned char DayEnvironmentHDRI019_1K_TONEMAPPED_jpg[] = {
0xbc, 0x06, 0x27, 0x9c, 0xf7, 0xe0, 0x0f, 0xd6, 0x9a, 0x25, 0xdc, 0xff, 0xbc, 0x06, 0x27, 0x9c, 0xf7, 0xe0, 0x0f, 0xd6, 0x9a, 0x25, 0xdc, 0xff,
0xd9 0xd9
}; };
const unsigned int DayEnvironmentHDRI019_1K_TONEMAPPED_jpg_len = 17065; const unsigned int DayEnvironmentHDRI019_1K_TONEMAPPED_jpg_len = 17065;
/*
MIT License
Copyright (c) 2025 Harvey Fong
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

View File

@ -858,3 +858,26 @@ public:
} }
} }
}; };
/*
MIT License
Copyright (c) 2025 Harvey Fong
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

View File

@ -207,10 +207,6 @@ The 't' field in the snapshot's 's.id' dictionary indicates the type of snapshot
#include <sys/wait.h> // For waitpid #include <sys/wait.h> // For waitpid
#endif #endif
//#include <efsw/FileSystem.hpp> // For file watching
//#include <efsw/System.hpp> // For file watching
//#include <efsw/efsw.hpp> // For file watching
dl::bella_sdk::Node essentialsToScene(dl::bella_sdk::Scene& belScene); dl::bella_sdk::Node essentialsToScene(dl::bella_sdk::Scene& belScene);
dl::bella_sdk::Node addModelToScene(dl::bella_sdk::Scene& belScene, dl::bella_sdk::Node& belWorld, const VmaxModel& vmaxModel, const std::vector<VmaxRGBA>& vmaxPalette, const std::array<VmaxMaterial, 8>& vmaxMaterial); dl::bella_sdk::Node addModelToScene(dl::bella_sdk::Scene& belScene, dl::bella_sdk::Node& belWorld, const VmaxModel& vmaxModel, const std::vector<VmaxRGBA>& vmaxPalette, const std::array<VmaxMaterial, 8>& vmaxMaterial);
@ -231,7 +227,7 @@ std::mutex unfileQueueMutex; // Add mutex for thread safety
std::mutex processQueueMutex; // Add mutex for thread safety std::mutex processQueueMutex; // Add mutex for thread safety
//Forward declares //Forward declares
void convertVmaxToBella( const dl::String& vmaxDirName); dl::bella_sdk::Scene convertVmaxToBella( const dl::String& vmaxDirName);
// Signal handler for ctrl-c // Signal handler for ctrl-c
void sigend( int ) { void sigend( int ) {
@ -245,7 +241,6 @@ void sigend( int ) {
exit(0); // Force exit after cleanup exit(0); // Force exit after cleanup
} }
static int s_logCtx = 0; static int s_logCtx = 0;
static void log(void* /*ctx*/, dl::LogType type, const char* msg) static void log(void* /*ctx*/, dl::LogType type, const char* msg)
{ {
@ -274,6 +269,7 @@ static void log(void* /*ctx*/, dl::LogType type, const char* msg)
* - Track rendering progress * - Track rendering progress
* - Handle error conditions * - Handle error conditions
* - Store and retrieve the current progress state * - Store and retrieve the current progress state
* - Can be passed by reference unlike Engine
*/ */
struct MyEngineObserver : public dl::bella_sdk::EngineObserver struct MyEngineObserver : public dl::bella_sdk::EngineObserver
{ {
@ -342,8 +338,6 @@ static void log(void* /*ctx*/, dl::LogType type, const char* msg)
} }
}; };
int DL_main(dl::Args& args) { int DL_main(dl::Args& args) {
args.add("i", "input", "", "vmax directory or vmax.zip file"); args.add("i", "input", "", "vmax directory or vmax.zip file");
args.add("o", "output", "", "set output bella file name"); args.add("o", "output", "", "set output bella file name");
@ -370,229 +364,20 @@ int DL_main(dl::Args& args) {
std::cout << initializeThirdPartyLicences() << std::endl; std::cout << initializeThirdPartyLicences() << std::endl;
return 0; return 0;
} }
if (args.have("--input")) if (args.have("--input"))
{ {
dl::String bszName; dl::String bszName;
dl::String vmaxDirName; dl::String vmaxDirName = args.value("--input");
vmaxDirName = args.value("--input"); auto vmaxPath = dl::Path();
if (!vmaxPath.exists(vmaxDirName)) {
std::cout << "Cannot find directory " << vmaxDirName.buf() << std::endl;
return 0;
}
bszName = vmaxDirName.replace("vmax", "bsz"); bszName = vmaxDirName.replace("vmax", "bsz");
dl::bella_sdk::Scene belScene = convertVmaxToBella(vmaxDirName);
// Create a new scene
dl::bella_sdk::Scene belScene;
belScene.loadDefs();
auto belWorld = belScene.world(true);
// scene.json is the toplevel file that hierarchically defines the scene
// it contains nestable groups (containers) and objects (instances) that point to resources that define the object
// objects properties
// - transformation matrix
// objects resources
/// - reference a contentsN.vmaxb (lzfse compressed plist file) that contains a 256x256x256 voxel "model"
// - reference to a paletteN.png that defines the 256 24bit colors used in the 256x256x256 model
// - reference to a paletteN.settings.vmaxpsb (plist file) that defines the 8 materials used in the "model"
// In scenegraph parlance a group is a xform, a object is a transform with a child geometry
// multiple objects can point to the same model creating what is known as an instance
JsonVmaxSceneParser vmaxSceneParser;
vmaxSceneParser.parseScene((vmaxDirName+"/scene.json").buf());
#ifdef _DEBUG
vmaxSceneParser.printSummary();
#endif
std::map<std::string, JsonGroupInfo> jsonGroups = vmaxSceneParser.getGroups();
std::map<dl::String, dl::bella_sdk::Node> belGroupNodes; // Map of UUID to bella node
std::map<dl::String, dl::bella_sdk::Node> belCanonicalNodes; // Map of UUID to bella node
// First pass to create all the Bella nodes for the groups
for (const auto& [groupName, groupInfo] : jsonGroups) {
dl::String belGroupUUID = dl::String(groupName.c_str());
belGroupUUID = belGroupUUID.replace("-", "_"); // Make sure the group name is valid for a Bella node name
belGroupUUID = "_" + belGroupUUID; // Make sure the group name is valid for a Bella node name
belGroupNodes[belGroupUUID] = belScene.createNode("xform", belGroupUUID, belGroupUUID); // Create a Bella node for the group
VmaxMatrix4x4 objectMat4 = combineVmaxTransforms(groupInfo.rotation[0],
groupInfo.rotation[1],
groupInfo.rotation[2],
groupInfo.rotation[3],
groupInfo.position[0],
groupInfo.position[1],
groupInfo.position[2],
groupInfo.scale[0],
groupInfo.scale[1],
groupInfo.scale[2]);
belGroupNodes[belGroupUUID]["steps"][0]["xform"] = dl::Mat4({
objectMat4.m[0][0], objectMat4.m[0][1], objectMat4.m[0][2], objectMat4.m[0][3],
objectMat4.m[1][0], objectMat4.m[1][1], objectMat4.m[1][2], objectMat4.m[1][3],
objectMat4.m[2][0], objectMat4.m[2][1], objectMat4.m[2][2], objectMat4.m[2][3],
objectMat4.m[3][0], objectMat4.m[3][1], objectMat4.m[3][2], objectMat4.m[3][3]
});
}
// json file is allowed the parent to be defined after the child, requiring us to create all the bella nodes before we can parent them
for (const auto& [groupName, groupInfo] : jsonGroups) {
dl::String belGroupUUID = dl::String(groupName.c_str());
belGroupUUID = belGroupUUID.replace("-", "_");
belGroupUUID = "_" + belGroupUUID;
if (groupInfo.parentId == "") {
belGroupNodes[belGroupUUID].parentTo(belWorld); // Group without a parent is a child of the world
} else {
dl::String belPPPGroupUUID = dl::String(groupInfo.parentId.c_str());
belPPPGroupUUID = belPPPGroupUUID.replace("-", "_");
belPPPGroupUUID = "_" + belPPPGroupUUID;
dl::bella_sdk::Node myParentGroup = belGroupNodes[belPPPGroupUUID]; // Get bella obj
belGroupNodes[belGroupUUID].parentTo(myParentGroup); // Group underneath a group
}
}
// Efficiently process unique models by examining only the first instance of each model type.
// Example: If we have 100 instances of 3 different models:
// "model1.vmaxb": [instance1, instance2, ..., instance50],
// "model2.vmaxb": [instance1, ..., instance30],
// "model3.vmaxb": [instance1, ..., instance20]
// This loop runs only 3 times (once per unique model), not 100 times (once per instance)
auto modelVmaxbMap = vmaxSceneParser.getModelContentVMaxbMap();
std::vector<VmaxModel> allModels;
std::vector<std::vector<VmaxRGBA>> vmaxPalettes; // one palette per model
std::vector<std::array<VmaxMaterial, 8>> vmaxMaterials; // one material per model
//std::vector<std::array<VmaxMaterial, 8>> allMaterials; // one material per model
//std::vector<std::vector<VmaxRGBA>> allPalettes;
essentialsToScene(belScene); // create the basic scene elements in Bella
// Loop over each model defined in scene.json and process the first instance
// This will be out canonical models, not instances
// todo rename model to objects as per vmax
for (const auto& [vmaxContentName, vmaxModelList] : modelVmaxbMap) {
VmaxModel currentVmaxModel(vmaxContentName);
const auto& jsonModelInfo = vmaxModelList.front(); // get the first model, others are instances at the scene level
std::vector<double> position = jsonModelInfo.position;
std::vector<double> rotation = jsonModelInfo.rotation;
std::vector<double> scale = jsonModelInfo.scale;
std::vector<double> extentCenter = jsonModelInfo.extentCenter;
// Get this models colors from the paletteN.png
dl::String pngName = vmaxDirName + "/" + jsonModelInfo.paletteFile.c_str();
auto materialName = pngName.replace(".png", ".settings.vmaxpsb");
vmaxPalettes.push_back(read256x1PaletteFromPNG(pngName.buf())); // gather all models palettes
if (vmaxPalettes.empty()) { throw std::runtime_error("Failed to read palette from: png " ); }
// Read contentsN.vmaxb plist file, lzfse compressed
dl::String modelFileName = vmaxDirName + "/" + jsonModelInfo.dataFile.c_str();
plist_t plist_model_root = readPlist(modelFileName.buf(), true); // decompress=true
// There will one or more snapshots in the plist file
// Each snapshot is a capture of a 32x32x32 voxel chunk at a point in time
// A chunkId is a morton code that uniquely identifies the chunk is a 8x8x8 array within 256x256x256 model volume
// The highest index snapshot is the current state of the model
// One can traverse the snapshots in reverse to get the history of the model frok inception
plist_t plist_snapshots_array = plist_dict_get_item(plist_model_root, "snapshots");
uint32_t snapshots_array_size = plist_array_get_size(plist_snapshots_array);
#ifdef _DEBUG
std::cout << "vmaxContentName: " << vmaxContentName << std::endl;
std::cout << "snapshots_array_size: " << snapshots_array_size << std::endl;
#endif
// Create a VmaxModel object
for (uint32_t i = 0; i < snapshots_array_size; i++) {
plist_t plist_snapshot = plist_array_get_item(plist_snapshots_array, i);
plist_t plist_chunk = getNestedPlistNode(plist_snapshot, {"s", "id", "c"});
plist_t plist_datastream = getNestedPlistNode(plist_snapshot, {"s", "ds"});
uint64_t chunkID;
plist_get_uint_val(plist_chunk, &chunkID);
VmaxChunkInfo chunkInfo = vmaxChunkInfo(plist_snapshot);
#ifdef _DEBUG
std::cout << "\nChunkID: " << chunkInfo.id << std::endl;
std::cout << "TypeID: " << chunkInfo.type << std::endl;
std::cout << "MortonCode: " << chunkInfo.mortoncode << "\n" <<std::endl;
#endif
std::vector<VmaxVoxel> xvoxels = vmaxVoxelInfo(plist_datastream, chunkInfo.id, chunkInfo.mortoncode);
for (const auto& voxel : xvoxels) {
currentVmaxModel.addVoxel(voxel.x, voxel.y, voxel.z, voxel.material, voxel.palette ,chunkInfo.id, chunkInfo.mortoncode);
}
}
allModels.push_back(currentVmaxModel);
// Parse the materials store in paletteN.settings.vmaxpsb
plist_t plist_material = readPlist(materialName.buf(),false); // decompress=false
std::array<VmaxMaterial, 8> currentMaterials = getVmaxMaterials(plist_material);
vmaxMaterials.push_back(currentMaterials);
}
// Need to access voxels by material and color groupings
// Models are canonical models, not instances
// Vmax objects are instances of models
// First create canonical models and they are NOT attached to belWorld
int modelIndex=0;
for (const auto& eachModel : allModels) {
dl::bella_sdk::Node belModel = addModelToScene(belScene, belWorld, eachModel, vmaxPalettes[modelIndex], vmaxMaterials[modelIndex]);
dl::String lllmodelName = dl::String(eachModel.vmaxbFileName.c_str());
dl::String lllcanonicalName = lllmodelName.replace(".vmaxb", "");
belCanonicalNodes[lllcanonicalName.buf()] = belModel;
std::cout << lllcanonicalName.buf() << std::endl;
modelIndex++;
}
// Second Loop through each vmax object and create an instance of the canonical model
// This is the instances of the models, we did a pass to create the canonical models earlier
for (const auto& [vmaxContentName, vmaxModelList] : modelVmaxbMap) {
VmaxModel currentVmaxModel(vmaxContentName);
for(const auto& jsonModelInfo : vmaxModelList) {
std::vector<double> position = jsonModelInfo.position;
std::vector<double> rotation = jsonModelInfo.rotation;
std::vector<double> scale = jsonModelInfo.scale;
std::vector<double> extentCenter = jsonModelInfo.extentCenter;
auto jsonParentId = jsonModelInfo.parentId;
auto belParentId = dl::String(jsonParentId.c_str());
dl::String belParentGroupUUID = belParentId.replace("-", "_");
belParentGroupUUID = "_" + belParentGroupUUID;
auto belObjectId = dl::String(jsonModelInfo.id.c_str());
belObjectId = belObjectId.replace("-", "_");
belObjectId = "_" + belObjectId;
dl::String getCanonicalName = dl::String(jsonModelInfo.dataFile.c_str());
dl::String canonicalName = getCanonicalName.replace(".vmaxb", "");
//get bel node from canonical name
auto belCanonicalNode = belCanonicalNodes[canonicalName.buf()];
auto foofoo = belScene.findNode(canonicalName);
VmaxMatrix4x4 objectMat4 = combineVmaxTransforms(rotation[0],
rotation[1],
rotation[2],
rotation[3],
position[0],
position[1],
position[2],
scale[0],
scale[1],
scale[2]);
auto belNodeObjectInstance = belScene.createNode("xform", belObjectId, belObjectId);
belNodeObjectInstance["steps"][0]["xform"] = dl::Mat4({
objectMat4.m[0][0], objectMat4.m[0][1], objectMat4.m[0][2], objectMat4.m[0][3],
objectMat4.m[1][0], objectMat4.m[1][1], objectMat4.m[1][2], objectMat4.m[1][3],
objectMat4.m[2][0], objectMat4.m[2][1], objectMat4.m[2][2], objectMat4.m[2][3],
objectMat4.m[3][0], objectMat4.m[3][1], objectMat4.m[3][2], objectMat4.m[3][3]
});
if (jsonParentId == "") {
belNodeObjectInstance.parentTo(belScene.world());
} else {
belNodeObjectInstance.parentTo(belGroupNodes[belParentGroupUUID]);
}
foofoo.parentTo(belNodeObjectInstance);
}
}
// Write Bella File .bsz=compressed .bsa=ascii .bsx=binary
belScene.write(bszName.buf()); belScene.write(bszName.buf());
} }
if (args.have("--watchdir")) { if (args.have("--watchdir")) {
std::cout << "VmaxTUI server started ..." << std::endl; std::cout << "VmaxTUI server started ..." << std::endl;
@ -913,10 +698,10 @@ dl::bella_sdk::Node addModelToScene(dl::bella_sdk::Scene& belScene, dl::bella_sd
} }
void convertVmaxToBella( const dl::String& vmaxDirName) dl::bella_sdk::Scene convertVmaxToBella( const dl::String& vmaxDirName)
{ {
dl::String bszName; //dl::String bszName;
bszName = vmaxDirName.replace(".vmax", ".bsz"); //bszName = vmaxDirName.replace(".vmax", ".bsz");
// Create a new scene // Create a new scene
dl::bella_sdk::Scene belScene; dl::bella_sdk::Scene belScene;
@ -1129,7 +914,5 @@ void convertVmaxToBella( const dl::String& vmaxDirName)
foofoo.parentTo(belNodeObjectInstance); foofoo.parentTo(belNodeObjectInstance);
} }
} }
return belScene;
belScene.write(bszName.buf());
active_render = false;
} }