first working ogt mesh, added --bevel, --mode:mesh
This commit is contained in:
parent
c7da7c0a6f
commit
e427eab5ff
@ -18,7 +18,8 @@ workdir/
|
|||||||
├── bella_scene_sdk/
|
├── bella_scene_sdk/
|
||||||
├── libplist/
|
├── libplist/
|
||||||
├── lzfse/
|
├── lzfse/
|
||||||
└── vox2bella/
|
├── opengametools/
|
||||||
|
└── vmax2bella/
|
||||||
```
|
```
|
||||||
|
|
||||||
# MacOS
|
# MacOS
|
||||||
@ -42,6 +43,7 @@ cd libplist
|
|||||||
make -j4
|
make -j4
|
||||||
install_name_tool -id @rpath/libplist-2.0.4.dylib src/.libs/libplist-2.0.4.dylib
|
install_name_tool -id @rpath/libplist-2.0.4.dylib src/.libs/libplist-2.0.4.dylib
|
||||||
cd ..
|
cd ..
|
||||||
|
git clone https://github.com/jpaver/opengametools.git
|
||||||
git clone https://github.com/oomer/vmax2bella.git
|
git clone https://github.com/oomer/vmax2bella.git
|
||||||
cd vmax2bella
|
cd vmax2bella
|
||||||
make
|
make
|
||||||
@ -62,6 +64,7 @@ cd libplist
|
|||||||
./autogen.sh --prefix=$PWD/install --without-cython
|
./autogen.sh --prefix=$PWD/install --without-cython
|
||||||
make -j4
|
make -j4
|
||||||
cd ..
|
cd ..
|
||||||
|
git clone https://github.com/jpaver/opengametools.git
|
||||||
git clone https://github.com/oomer/vmax2bella.git
|
git clone https://github.com/oomer/vmax2bella.git
|
||||||
cd vmax2bella
|
cd vmax2bella
|
||||||
make
|
make
|
||||||
@ -74,7 +77,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/jpaver/opengametools.git
|
||||||
git clone https://github.com/oomer/vmax2bella.git
|
git clone https://github.com/oomer/vmax2bella.git
|
||||||
cd vmax2bella
|
cd vmax2bella
|
||||||
msbuild vox2bella.vcxproj /p:Configuration=release /p:Platform=x64 /p:PlatformToolset=v143
|
msbuild vox2bella.vcxproj /p:Configuration=release /p:Platform=x64 /p:PlatformToolset=v143
|
||||||
|
|||||||
236
oomer_voxel_ogt.h
Normal file
236
oomer_voxel_ogt.h
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
// oomer wrapper code for opengametools voxel conversion
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "oomer_voxel_vmax.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "../opengametools/src/ogt_vox.h"
|
||||||
|
|
||||||
|
// Only define implementation once to avoid redefinition errors
|
||||||
|
#ifndef OGT_VOXEL_MESHIFY_IMPLEMENTATION
|
||||||
|
#define OGT_VOXEL_MESHIFY_IMPLEMENTATION
|
||||||
|
#endif
|
||||||
|
#include "../opengametools/src/ogt_voxel_meshify.h"
|
||||||
|
|
||||||
|
// Convert a VmaxModel to an ogt_vox_model
|
||||||
|
// Note: The returned ogt_vox_model must be freed using ogt_vox_free when no longer needed
|
||||||
|
/*ogt_vox_model* convert_vmax_to_ogt_vox(const VmaxModel& vmaxModel) {
|
||||||
|
// Use max dimensions from vmaxModel
|
||||||
|
// Add 1 to get the actual size (since coordinates are 0-based)
|
||||||
|
uint32_t size_x = vmaxModel.maxx+1;
|
||||||
|
uint32_t size_y = vmaxModel.maxy+1;
|
||||||
|
uint32_t size_z = vmaxModel.maxz+1;
|
||||||
|
|
||||||
|
// Add some safety checks
|
||||||
|
if (size_x > 256 || size_y > 256 || size_z > 256) {
|
||||||
|
std::cout << "Warning: Model dimensions exceed 256 limit. Clamping to 256." << std::endl;
|
||||||
|
size_x = std::min(size_x, 256u);
|
||||||
|
size_y = std::min(size_y, 256u);
|
||||||
|
size_z = std::min(size_z, 256u);
|
||||||
|
}
|
||||||
|
if (size_x == 0 || size_y == 0 || size_z == 0) {
|
||||||
|
std::cout << "Error: Model has zero dimensions. Setting minimum size of 1x1x1." << std::endl;
|
||||||
|
size_x = std::max(size_x, 1u);
|
||||||
|
size_y = std::max(size_y, 1u);
|
||||||
|
size_z = std::max(size_z, 1u);
|
||||||
|
}
|
||||||
|
// Create the voxel data array (initialized to 0, which means empty in ogt_vox)
|
||||||
|
size_t voxel_count = size_x * size_y * size_z;
|
||||||
|
uint8_t* voxel_data = (uint8_t*)ogt_vox_malloc(voxel_count);
|
||||||
|
if (!voxel_data) {
|
||||||
|
std::cout << "Error: Failed to allocate memory for voxel data" << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
memset(voxel_data, 0, voxel_count); // Initialize all to 0 (empty)
|
||||||
|
|
||||||
|
// Fill the voxel data array with color indices
|
||||||
|
int voxel_count_populated = 0;
|
||||||
|
for (uint32_t x = 0; x < size_x; x++) {
|
||||||
|
for (uint32_t y = 0; y < size_y; y++) {
|
||||||
|
for (uint32_t z = 0; z < size_z; z++) {
|
||||||
|
// Calculate the index in the 1D array
|
||||||
|
size_t index = x + (y * size_x) + (z * size_x * size_y);
|
||||||
|
|
||||||
|
if (index < voxel_count) {
|
||||||
|
try {
|
||||||
|
// Use the new hasVoxelsAt and getVoxelsAt methods instead of directly accessing voxelsSpatial
|
||||||
|
if (vmaxModel.hasVoxelsAt(x, y, z)) {
|
||||||
|
const std::vector<VmaxVoxel>& voxels = vmaxModel.getVoxelsAt(x, y, z);
|
||||||
|
if (!voxels.empty()) {
|
||||||
|
uint8_t palette_index = voxels[0].palette;
|
||||||
|
if (palette_index == 0) palette_index = 1; // If palette is 0, use 1 instead to make it visible
|
||||||
|
voxel_data[index] = palette_index;
|
||||||
|
voxel_count_populated++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If no voxels at this position, it remains 0 (empty)
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
std::cout << "ERROR: Exception accessing voxels at [" << x << "][" << y << "][" << z
|
||||||
|
<< "]: " << e.what() << std::endl;
|
||||||
|
ogt_vox_free(voxel_data);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and initialize the ogt_vox_model
|
||||||
|
ogt_vox_model* model = (ogt_vox_model*)ogt_vox_malloc(sizeof(ogt_vox_model));
|
||||||
|
if (!model) {
|
||||||
|
std::cout << "Error: Failed to allocate memory for ogt_vox_model" << std::endl;
|
||||||
|
ogt_vox_free(voxel_data);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
model->size_x = size_x;
|
||||||
|
model->size_y = size_y;
|
||||||
|
model->size_z = size_z;
|
||||||
|
model->voxel_data = voxel_data;
|
||||||
|
|
||||||
|
// Calculate a simple hash for the voxel data
|
||||||
|
uint32_t hash = 0;
|
||||||
|
for (size_t i = 0; i < voxel_count; i++) {
|
||||||
|
hash = hash * 65599 + voxel_data[i];
|
||||||
|
}
|
||||||
|
model->voxel_hash = hash;
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Convert a vector of VmaxVoxel to an ogt_vox_model
|
||||||
|
// Note: The returned ogt_vox_model must be freed using ogt_vox_free when no longer needed
|
||||||
|
ogt_vox_model* convert_voxelsoftype_to_ogt_vox(const std::vector<VmaxVoxel>& voxelsOfType) {
|
||||||
|
// Find the maximum dimensions from the voxels
|
||||||
|
uint32_t size_x = 0;
|
||||||
|
uint32_t size_y = 0;
|
||||||
|
uint32_t size_z = 0;
|
||||||
|
|
||||||
|
// WARNING must add 1 to each dimension
|
||||||
|
// because voxel coordinates are 0-based
|
||||||
|
for (const auto& voxel : voxelsOfType) {
|
||||||
|
size_x = std::max(size_x, static_cast<uint32_t>(voxel.x)+1); // this seems wasteful
|
||||||
|
size_y = std::max(size_y, static_cast<uint32_t>(voxel.y)+1);
|
||||||
|
size_z = std::max(size_z, static_cast<uint32_t>(voxel.z)+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add some safety checks
|
||||||
|
// This is a dense voxel model, so we need to make sure it's not too large
|
||||||
|
// todo use a sparse storage like morton
|
||||||
|
if (size_x > 256 || size_y > 256 || size_z > 256) {
|
||||||
|
std::cout << "Warning: Model dimensions exceed 256 limit. Clamping to 256." << std::endl;
|
||||||
|
size_x = std::min(size_x, 256u);
|
||||||
|
size_y = std::min(size_y, 256u);
|
||||||
|
size_z = std::min(size_z, 256u);
|
||||||
|
}
|
||||||
|
if (size_x == 0 || size_y == 0 || size_z == 0) {
|
||||||
|
std::cout << "Error: Model has zero dimensions. Setting minimum size of 1x1x1." << std::endl;
|
||||||
|
size_x = std::max(size_x, 1u);
|
||||||
|
size_y = std::max(size_y, 1u);
|
||||||
|
size_z = std::max(size_z, 1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the voxel data array (initialized to 0, which means empty in ogt_vox)
|
||||||
|
size_t voxel_count = size_x * size_y * size_z;
|
||||||
|
uint8_t* voxel_data = (uint8_t*)ogt_vox_malloc(voxel_count);
|
||||||
|
if (!voxel_data) {
|
||||||
|
std::cout << "Error: Failed to allocate memory for voxel data" << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
memset(voxel_data, 0, voxel_count); // Initialize all to 0 (empty)
|
||||||
|
|
||||||
|
// Fill the voxel data array with color indices
|
||||||
|
int voxel_count_populated = 0;
|
||||||
|
|
||||||
|
// Loop through the vector of voxels directly
|
||||||
|
for (const auto& voxel : voxelsOfType) {
|
||||||
|
// Get the coordinates and palette
|
||||||
|
uint32_t x = voxel.x;
|
||||||
|
uint32_t y = voxel.y;
|
||||||
|
uint32_t z = voxel.z;
|
||||||
|
|
||||||
|
// Skip voxels outside our valid range
|
||||||
|
if (x >= size_x || y >= size_y || z >= size_z)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Calculate the index in the 1D array
|
||||||
|
size_t index = x + (y * size_x) + (z * size_x * size_y);
|
||||||
|
|
||||||
|
if (index < voxel_count) {
|
||||||
|
uint8_t palette_index = 0; // hardcoded for now
|
||||||
|
if (palette_index == 0) palette_index = 1; // If palette is 0, use 1 instead to make it visible
|
||||||
|
voxel_data[index] = palette_index;
|
||||||
|
voxel_count_populated++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the model
|
||||||
|
ogt_vox_model* model = (ogt_vox_model*)ogt_vox_malloc(sizeof(ogt_vox_model));
|
||||||
|
if (!model) {
|
||||||
|
std::cout << "Error: Failed to allocate memory for model" << std::endl;
|
||||||
|
ogt_vox_free(voxel_data);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
model->size_x = size_x;
|
||||||
|
model->size_y = size_y;
|
||||||
|
model->size_z = size_z;
|
||||||
|
model->voxel_data = voxel_data;
|
||||||
|
|
||||||
|
// Calculate a simple hash for the voxel data
|
||||||
|
uint32_t hash = 0;
|
||||||
|
for (size_t i = 0; i < voxel_count; i++) {
|
||||||
|
hash = hash * 65599 + voxel_data[i];
|
||||||
|
}
|
||||||
|
model->voxel_hash = hash;
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free resources allocated for an ogt_vox_model created by convert_vmax_to_ogt_vox
|
||||||
|
void free_ogt_vox_model(ogt_vox_model* model) {
|
||||||
|
if (model) {
|
||||||
|
if (model->voxel_data) {
|
||||||
|
ogt_vox_free((void*)model->voxel_data);
|
||||||
|
}
|
||||||
|
ogt_vox_free(model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free resources allocated for an ogt_vox_scene created by create_ogt_vox_scene_from_vmax
|
||||||
|
/*void free_ogt_vox_scene(ogt_vox_scene* scene) {
|
||||||
|
if (scene) {
|
||||||
|
// Free each model
|
||||||
|
for (uint32_t i = 0; i < scene->num_models; i++) {
|
||||||
|
free_ogt_vox_model((ogt_vox_model*)scene->models[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free pointers
|
||||||
|
if (scene->models) ogt_vox_free((void*)scene->models);
|
||||||
|
if (scene->instances) ogt_vox_free((void*)scene->instances);
|
||||||
|
if (scene->layers) ogt_vox_free((void*)scene->layers);
|
||||||
|
|
||||||
|
// Free the scene itself
|
||||||
|
ogt_vox_free(scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Custom allocator functions for ogt_voxel_meshify
|
||||||
|
static void* voxel_meshify_malloc(size_t size, void* user_data) {
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void voxel_meshify_free(void* ptr, void* user_data) {
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
@ -233,7 +233,17 @@ struct VmaxMaterial {
|
|||||||
bool volumetric; // future use
|
bool volumetric; // future use
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VmaxVoxelGrid {
|
||||||
|
// dimensions of the voxel grid
|
||||||
|
uint32_t size_x, size_y, size_z;
|
||||||
|
// voxel data
|
||||||
|
uint8_t* voxel_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Create a structure to represent a model with its voxels with helper functions
|
// Create a structure to represent a model with its voxels with helper functions
|
||||||
|
// since the xyz coords are at the voxel level, we need an accessor to walk it sequentially
|
||||||
|
// maybe I create a new structure called VmaxVoxelGrid
|
||||||
struct VmaxModel {
|
struct VmaxModel {
|
||||||
// Model identifier or name
|
// Model identifier or name
|
||||||
std::string vmaxbFileName; // file name is used like a key
|
std::string vmaxbFileName; // file name is used like a key
|
||||||
@ -243,32 +253,118 @@ struct VmaxModel {
|
|||||||
// Second dimension: color (1-255, index 0 unused since color 0 means no voxel)
|
// Second dimension: color (1-255, index 0 unused since color 0 means no voxel)
|
||||||
std::vector<VmaxVoxel> voxels[8][256];
|
std::vector<VmaxVoxel> voxels[8][256];
|
||||||
|
|
||||||
|
// EDUCATIONAL NOTES ON DUAL DATA STRUCTURES FOR VOXELS:
|
||||||
|
// ----------------------------------------------------
|
||||||
|
// This class uses two different data structures to store the same voxel data,
|
||||||
|
// each optimized for different access patterns:
|
||||||
|
//
|
||||||
|
// 1. voxels[8][256] - Organizes voxels by material and color
|
||||||
|
// - Efficient for queries like "give me all voxels of material 2, color 37"
|
||||||
|
// - Poor for spatial queries like "what's at position (x,y,z)?"
|
||||||
|
//
|
||||||
|
// 2. voxelsSpatial - Organizes voxels by their spatial position
|
||||||
|
// - Efficient for spatial queries like "what's at position (x,y,z)?"
|
||||||
|
// - Uses a map for memory efficiency with sparse data
|
||||||
|
//
|
||||||
|
// Tradeoffs:
|
||||||
|
// - Memory: We use more memory by storing voxels twice
|
||||||
|
// - Performance: We get optimal performance for both types of queries
|
||||||
|
// - Complexity: We need to maintain both structures in sync
|
||||||
|
//
|
||||||
|
// For novice programmers: This is a common technique in game/graphics programming
|
||||||
|
// where performance is critical. We're trading some extra memory for faster access.
|
||||||
|
|
||||||
|
// Using a map for sparse 3D data instead of a fixed-size 3D array
|
||||||
|
// Key format: (x << 16) | (y << 8) | z
|
||||||
|
// This approach is memory-efficient for sparse data (mostly empty space)
|
||||||
|
// A 3D array would need 256³ = 16.7 million elements even if most are empty!
|
||||||
|
|
||||||
|
|
||||||
|
// todo we need to do morton decoing using chunkid to get x,y,z
|
||||||
|
std::map<uint32_t, std::vector<VmaxVoxel>> voxelsSpatial;
|
||||||
|
|
||||||
// Each model has local 0-7 materials
|
// Each model has local 0-7 materials
|
||||||
std::array<VmaxMaterial, 8> materials;
|
std::array<VmaxMaterial, 8> materials;
|
||||||
// Each model has local colors
|
// Each model has local colors
|
||||||
std::array<VmaxRGBA, 256> colors;
|
std::array<VmaxRGBA, 256> colors;
|
||||||
|
uint8_t maxx=0, maxy=0, maxz=0;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
VmaxModel(const std::string& modelName) : vmaxbFileName(modelName) {
|
VmaxModel(const std::string& modelName) : vmaxbFileName(modelName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to create a key for the voxelsSpatial map
|
||||||
|
static uint32_t makeVoxelKey(uint8_t x, uint8_t y, uint8_t z) {
|
||||||
|
return (static_cast<uint32_t>(x) << 16) | (static_cast<uint32_t>(y) << 8) | static_cast<uint32_t>(z);
|
||||||
|
}
|
||||||
|
|
||||||
// Add a voxel to this model
|
// Add a voxel to this model
|
||||||
|
// EDUCATIONAL NOTE:
|
||||||
|
// Notice how we maintain BOTH data structures when adding a voxel.
|
||||||
|
// This is a key practice when using dual data structures - keep them in sync
|
||||||
|
// by updating both whenever data changes.
|
||||||
void addVoxel(int x, int y, int z, int material, int color, int chunk, int chunkMin) {
|
void addVoxel(int x, int y, int z, int material, int color, int chunk, int chunkMin) {
|
||||||
|
|
||||||
|
//todo add chunk offset to x,y,z
|
||||||
|
//chunkMin is offset withing each chunk used earlier
|
||||||
|
uint32_t _tempx, _tempy, _tempz;
|
||||||
|
decodeMorton3DOptimized(chunk, _tempx, _tempy, _tempz); // index IS the morton code
|
||||||
|
int worldOffsetX = _tempx * 24; // get world loc within 256x256x256 grid
|
||||||
|
int worldOffsetY = _tempy * 24; // Don't know why we need to multiply by 24
|
||||||
|
int worldOffsetZ = _tempz * 24; // use to be 32
|
||||||
|
x += worldOffsetX;
|
||||||
|
y += worldOffsetY;
|
||||||
|
z += worldOffsetZ;
|
||||||
|
|
||||||
|
|
||||||
if (material >= 0 && material < 8 && color > 0 && color < 256) {
|
if (material >= 0 && material < 8 && color > 0 && color < 256) {
|
||||||
voxels[material][color].emplace_back(x, y, z, material, color, chunk, chunkMin);
|
voxels[material][color].emplace_back(x, y, z, material, color, chunk, chunkMin);
|
||||||
|
|
||||||
|
// Add to voxelsSpatial using the map approach
|
||||||
|
uint32_t key = makeVoxelKey(x, y, z);
|
||||||
|
//todo add chunk offset to x,y,z
|
||||||
|
voxelsSpatial[key].emplace_back(x, y, z, material, color, chunk, chunkMin);
|
||||||
|
|
||||||
|
if (x > maxx) maxx = x;
|
||||||
|
if (y > maxy) maxy = y;
|
||||||
|
if (z > maxz) maxz = z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a materials to this model
|
// Get voxels at a specific position
|
||||||
|
// EDUCATIONAL NOTE:
|
||||||
|
// This method demonstrates the power of our spatial index.
|
||||||
|
// Time complexity: O(log n) where n is the number of occupied positions.
|
||||||
|
// Without voxelsSpatial, we would need to scan through ALL voxels (potentially thousands)
|
||||||
|
// to find those at a specific position, which would be O(total_voxel_count).
|
||||||
|
const std::vector<VmaxVoxel>& getVoxelsAt(uint8_t x, uint8_t y, uint8_t z) const {
|
||||||
|
uint32_t key = makeVoxelKey(x, y, z);
|
||||||
|
auto it = voxelsSpatial.find(key);
|
||||||
|
if (it != voxelsSpatial.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
static const std::vector<VmaxVoxel> empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are voxels at a specific position
|
||||||
|
// Another spatial query that benefits from our map-based structure
|
||||||
|
bool hasVoxelsAt(uint8_t x, uint8_t y, uint8_t z) const {
|
||||||
|
uint32_t key = makeVoxelKey(x, y, z);
|
||||||
|
auto it = voxelsSpatial.find(key);
|
||||||
|
return (it != voxelsSpatial.end() && !it->second.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add materials to this model
|
||||||
void addMaterials(const std::array<VmaxMaterial, 8> newMaterials) {
|
void addMaterials(const std::array<VmaxMaterial, 8> newMaterials) {
|
||||||
materials = newMaterials;
|
materials = newMaterials;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a colors to this model
|
// Add colors to this model
|
||||||
void addColors(const std::array<VmaxRGBA, 256> newColors) {
|
void addColors(const std::array<VmaxRGBA, 256> newColors) {
|
||||||
colors = newColors;
|
colors = newColors;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all voxels of a specific material and color
|
// Get all voxels of a specific material and color
|
||||||
const std::vector<VmaxVoxel>& getVoxels(int material, int color) const {
|
const std::vector<VmaxVoxel>& getVoxels(int material, int color) const {
|
||||||
if (material >= 0 && material < 8 && color > 0 && color < 256) {
|
if (material >= 0 && material < 8 && color > 0 && color < 256) {
|
||||||
@ -288,7 +384,7 @@ struct VmaxModel {
|
|||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a map of used materials and their associated colors
|
// Get a map of used materials and their associated colors
|
||||||
std::map<int, std::set<int>> getUsedMaterialsAndColors() const {
|
std::map<int, std::set<int>> getUsedMaterialsAndColors() const {
|
||||||
std::map<int, std::set<int>> result;
|
std::map<int, std::set<int>> result;
|
||||||
|
|||||||
210
vmax2bella.cpp
210
vmax2bella.cpp
@ -178,13 +178,22 @@ The 't' field in the snapshot's 's.id' dictionary indicates the type of snapshot
|
|||||||
|
|
||||||
#include "oomer_voxel_vmax.h" // common vmax voxel code and structures
|
#include "oomer_voxel_vmax.h" // common vmax voxel code and structures
|
||||||
#include "oomer_misc.h" // common misc code
|
#include "oomer_misc.h" // common misc code
|
||||||
|
#include "oomer_voxel_ogt.h" // common opengametools voxel conversion wrappers
|
||||||
|
|
||||||
|
#define OGT_VOX_IMPLEMENTATION
|
||||||
|
#include "../opengametools/src/ogt_vox.h"
|
||||||
|
|
||||||
|
|
||||||
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::Args& args, 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 add_ogt_mesh_to_scene(dl::String bellaName, ogt_mesh* ogtMesh, dl::bella_sdk::Scene& belScene, dl::bella_sdk::Node& belWorld );
|
||||||
|
|
||||||
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");
|
||||||
|
args.add("mo", "mode", "", "mode for output, mesh, voxel, or both");
|
||||||
|
args.add("mt", "meshtype", "", "meshtype classic, greedy, other");
|
||||||
|
args.add("be", "bevel", "", "add bevel to material");
|
||||||
args.add("tp", "thirdparty", "", "prints third party licenses");
|
args.add("tp", "thirdparty", "", "prints third party licenses");
|
||||||
args.add("li", "licenseinfo", "", "prints license info");
|
args.add("li", "licenseinfo", "", "prints license info");
|
||||||
|
|
||||||
@ -211,9 +220,11 @@ int DL_main(dl::Args& args) {
|
|||||||
if (args.have("--input"))
|
if (args.have("--input"))
|
||||||
{
|
{
|
||||||
dl::String bszName;
|
dl::String bszName;
|
||||||
|
dl::String objName;
|
||||||
dl::String vmaxDirName;
|
dl::String vmaxDirName;
|
||||||
vmaxDirName = args.value("--input");
|
vmaxDirName = args.value("--input");
|
||||||
bszName = vmaxDirName.replace("vmax", "bsz");
|
bszName = vmaxDirName.replace("vmax", "bsz");
|
||||||
|
objName = vmaxDirName.replace("vmax", "obj");
|
||||||
|
|
||||||
// Create a new scene
|
// Create a new scene
|
||||||
dl::bella_sdk::Scene belScene;
|
dl::bella_sdk::Scene belScene;
|
||||||
@ -294,8 +305,6 @@ int DL_main(dl::Args& args) {
|
|||||||
std::vector<VmaxModel> allModels;
|
std::vector<VmaxModel> allModels;
|
||||||
std::vector<std::vector<VmaxRGBA>> vmaxPalettes; // one palette per model
|
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>> 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
|
essentialsToScene(belScene); // create the basic scene elements in Bella
|
||||||
|
|
||||||
@ -311,19 +320,6 @@ int DL_main(dl::Args& args) {
|
|||||||
std::vector<double> scale = jsonModelInfo.scale;
|
std::vector<double> scale = jsonModelInfo.scale;
|
||||||
std::vector<double> extentCenter = jsonModelInfo.extentCenter;
|
std::vector<double> extentCenter = jsonModelInfo.extentCenter;
|
||||||
|
|
||||||
|
|
||||||
/*VmaxMatrix4x4 modelMat4 = combineVmaxTransforms(rotation[0],
|
|
||||||
rotation[1],
|
|
||||||
rotation[2],
|
|
||||||
rotation[3],
|
|
||||||
position[0],
|
|
||||||
position[1],
|
|
||||||
position[2],
|
|
||||||
scale[0],
|
|
||||||
scale[1],
|
|
||||||
scale[2]);*/
|
|
||||||
//modelMatrix = scaleMatrix * modelMatrix * transMatrix;
|
|
||||||
|
|
||||||
// Get file names
|
// Get file names
|
||||||
dl::String materialName = vmaxDirName + "/" + jsonModelInfo.paletteFile.c_str();
|
dl::String materialName = vmaxDirName + "/" + jsonModelInfo.paletteFile.c_str();
|
||||||
materialName = materialName.replace(".png", ".settings.vmaxpsb");
|
materialName = materialName.replace(".png", ".settings.vmaxpsb");
|
||||||
@ -381,8 +377,13 @@ int DL_main(dl::Args& args) {
|
|||||||
std::cout << modelIndex << "Model: " << eachModel.vmaxbFileName << std::endl;
|
std::cout << modelIndex << "Model: " << eachModel.vmaxbFileName << std::endl;
|
||||||
std::cout << "Voxel Count Model: " << eachModel.getTotalVoxelCount() << std::endl;
|
std::cout << "Voxel Count Model: " << eachModel.getTotalVoxelCount() << std::endl;
|
||||||
|
|
||||||
dl::bella_sdk::Node belModel = addModelToScene(belScene, belWorld, eachModel, vmaxPalettes[modelIndex], vmaxMaterials[modelIndex]);
|
dl::bella_sdk::Node belModel = addModelToScene( args,
|
||||||
// TODO add to a map of canonical models
|
belScene,
|
||||||
|
belWorld,
|
||||||
|
eachModel,
|
||||||
|
vmaxPalettes[modelIndex],
|
||||||
|
vmaxMaterials[modelIndex]);
|
||||||
|
// TODO add to a map00000 of canonical models
|
||||||
dl::String lllmodelName = dl::String(eachModel.vmaxbFileName.c_str());
|
dl::String lllmodelName = dl::String(eachModel.vmaxbFileName.c_str());
|
||||||
dl::String lllcanonicalName = lllmodelName.replace(".vmaxb", "");
|
dl::String lllcanonicalName = lllmodelName.replace(".vmaxb", "");
|
||||||
std::cout << "========lllcanonicalName: " << lllcanonicalName.buf() << std::endl;
|
std::cout << "========lllcanonicalName: " << lllcanonicalName.buf() << std::endl;
|
||||||
@ -402,12 +403,12 @@ int DL_main(dl::Args& args) {
|
|||||||
std::vector<double> extentCenter = jsonModelInfo.extentCenter;
|
std::vector<double> extentCenter = jsonModelInfo.extentCenter;
|
||||||
auto jsonParentId = jsonModelInfo.parentId;
|
auto jsonParentId = jsonModelInfo.parentId;
|
||||||
auto belParentId = dl::String(jsonParentId.c_str());
|
auto belParentId = dl::String(jsonParentId.c_str());
|
||||||
dl::String belParentGroupUUID = belParentId.replace("-", "_");
|
dl::String belParentGroupUUID = belParentId.replace("-", "_"); // Make sure the group name is valid for a Bella node name
|
||||||
belParentGroupUUID = "_" + belParentGroupUUID;
|
belParentGroupUUID = "_" + belParentGroupUUID; // Make sure the group name is valid for a Bella node name
|
||||||
|
|
||||||
auto belObjectId = dl::String(jsonModelInfo.id.c_str());
|
auto belObjectId = dl::String(jsonModelInfo.id.c_str());
|
||||||
belObjectId = belObjectId.replace("-", "_");
|
belObjectId = belObjectId.replace("-", "_"); // Make sure the object name is valid for a Bella node name
|
||||||
belObjectId = "_" + belObjectId;
|
belObjectId = "_" + belObjectId; // Make sure the object name is valid for a Bella node name
|
||||||
|
|
||||||
dl::String getCanonicalName = dl::String(jsonModelInfo.dataFile.c_str());
|
dl::String getCanonicalName = dl::String(jsonModelInfo.dataFile.c_str());
|
||||||
dl::String canonicalName = getCanonicalName.replace(".vmaxb", "");
|
dl::String canonicalName = getCanonicalName.replace(".vmaxb", "");
|
||||||
@ -415,7 +416,6 @@ int DL_main(dl::Args& args) {
|
|||||||
auto belCanonicalNode = belCanonicalNodes[canonicalName.buf()];
|
auto belCanonicalNode = belCanonicalNodes[canonicalName.buf()];
|
||||||
auto foofoo = belScene.findNode(canonicalName);
|
auto foofoo = belScene.findNode(canonicalName);
|
||||||
|
|
||||||
|
|
||||||
VmaxMatrix4x4 objectMat4 = combineVmaxTransforms(rotation[0],
|
VmaxMatrix4x4 objectMat4 = combineVmaxTransforms(rotation[0],
|
||||||
rotation[1],
|
rotation[1],
|
||||||
rotation[2],
|
rotation[2],
|
||||||
@ -438,7 +438,8 @@ int DL_main(dl::Args& args) {
|
|||||||
if (jsonParentId == "") {
|
if (jsonParentId == "") {
|
||||||
belNodeObjectInstance.parentTo(belScene.world());
|
belNodeObjectInstance.parentTo(belScene.world());
|
||||||
} else {
|
} else {
|
||||||
belNodeObjectInstance.parentTo(belGroupNodes[belParentGroupUUID]);
|
dl::bella_sdk::Node myParentGroup = belGroupNodes[belParentGroupUUID]; // Get bella obj
|
||||||
|
belNodeObjectInstance.parentTo(myParentGroup); // Group underneath a group
|
||||||
}
|
}
|
||||||
foofoo.parentTo(belNodeObjectInstance);
|
foofoo.parentTo(belNodeObjectInstance);
|
||||||
}
|
}
|
||||||
@ -493,7 +494,7 @@ dl::bella_sdk::Node essentialsToScene(dl::bella_sdk::Scene& belScene) {
|
|||||||
belColorDome["horizon"] = dl::Rgba{.85f, 0.76f, 0.294f, 1.0f};
|
belColorDome["horizon"] = dl::Rgba{.85f, 0.76f, 0.294f, 1.0f};
|
||||||
belColorDome["altitude"] = 14.0f;
|
belColorDome["altitude"] = 14.0f;
|
||||||
// Configure ground plane
|
// Configure ground plane
|
||||||
belGroundPlane["elevation"] = -.5f;
|
//belGroundPlane["elevation"] = -.5f;
|
||||||
belGroundPlane["material"] = belGroundMat;
|
belGroundPlane["material"] = belGroundMat;
|
||||||
|
|
||||||
/* Commented out: Sun configuration
|
/* Commented out: Sun configuration
|
||||||
@ -522,6 +523,10 @@ dl::bella_sdk::Node essentialsToScene(dl::bella_sdk::Scene& belScene) {
|
|||||||
auto belLiqVoxelForm = belScene.createNode("xform","oomerLiqVoxelXform","oomerLiqVoxelXform");
|
auto belLiqVoxelForm = belScene.createNode("xform","oomerLiqVoxelXform","oomerLiqVoxelXform");
|
||||||
auto belVoxelMat = belScene.createNode("orenNayar","oomerVoxelMat","oomerVoxelMat");
|
auto belVoxelMat = belScene.createNode("orenNayar","oomerVoxelMat","oomerVoxelMat");
|
||||||
auto belMeshVoxel = belScene.createNode("mesh", "oomerMeshVoxel");
|
auto belMeshVoxel = belScene.createNode("mesh", "oomerMeshVoxel");
|
||||||
|
auto belBevel = belScene.createNode("bevel", "oomerBevel");
|
||||||
|
belBevel["radius"] = 90.0f;
|
||||||
|
belBevel["samples"] =dl::UInt(6);
|
||||||
|
|
||||||
#include "resources/smoothcube.h"
|
#include "resources/smoothcube.h"
|
||||||
// Configure voxel box dimensions
|
// Configure voxel box dimensions
|
||||||
belVoxel["radius"] = 0.33f;
|
belVoxel["radius"] = 0.33f;
|
||||||
@ -554,7 +559,12 @@ dl::bella_sdk::Node essentialsToScene(dl::bella_sdk::Scene& belScene) {
|
|||||||
// The datastream contains the voxels for the snapshot
|
// The datastream contains the voxels for the snapshot
|
||||||
// The voxels are stored in chunks, each chunk is 8x8x8 voxels
|
// The voxels are stored in chunks, each chunk is 8x8x8 voxels
|
||||||
// The chunks are stored in a morton order
|
// The chunks are stored in a morton order
|
||||||
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::Args& args,
|
||||||
|
dl::bella_sdk::Scene& belScene,
|
||||||
|
dl::bella_sdk::Node& belWorld,
|
||||||
|
const VmaxModel& vmaxModel,
|
||||||
|
const std::vector<VmaxRGBA>& vmaxPalette,
|
||||||
|
const std::array<VmaxMaterial, 8>& vmaxMaterial) {
|
||||||
// Create Bella scene nodes for each voxel
|
// Create Bella scene nodes for each voxel
|
||||||
int i = 0;
|
int i = 0;
|
||||||
dl::String modelName = dl::String(vmaxModel.vmaxbFileName.c_str());
|
dl::String modelName = dl::String(vmaxModel.vmaxbFileName.c_str());
|
||||||
@ -568,30 +578,31 @@ dl::bella_sdk::Node addModelToScene(dl::bella_sdk::Scene& belScene, dl::bella_sd
|
|||||||
auto belMeshVoxel = belScene.findNode("oomerMeshVoxel");
|
auto belMeshVoxel = belScene.findNode("oomerMeshVoxel");
|
||||||
auto belVoxelForm = belScene.findNode("oomerVoxelXform");
|
auto belVoxelForm = belScene.findNode("oomerVoxelXform");
|
||||||
auto belLiqVoxelForm = belScene.findNode("oomerLiqVoxelXform");
|
auto belLiqVoxelForm = belScene.findNode("oomerLiqVoxelXform");
|
||||||
|
auto belBevel = belScene.findNode("oomerBevel");
|
||||||
|
|
||||||
auto modelXform = belScene.createNode("xform", canonicalName, canonicalName);
|
auto modelXform = belScene.createNode("xform", canonicalName, canonicalName);
|
||||||
modelXform["steps"][0]["xform"] = dl::Mat4 {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
|
modelXform["steps"][0]["xform"] = dl::Mat4 {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
|
||||||
for (const auto& [material, colorID] : vmaxModel.getUsedMaterialsAndColors()) {
|
for (const auto& [material, colorID] : vmaxModel.getUsedMaterialsAndColors()) {
|
||||||
for (int color : colorID) {
|
for (int color : colorID) {
|
||||||
auto belInstancer = belScene.createNode("instancer",
|
|
||||||
canonicalName + dl::String("Material") + dl::String(material) + dl::String("Color") + dl::String(color));
|
auto thisname = canonicalName + dl::String("Material") + dl::String(material) + dl::String("Color") + dl::String(color);
|
||||||
auto xformsArray = dl::ds::Vector<dl::Mat4f>();
|
|
||||||
belInstancer["steps"][0]["xform"] = dl::Mat4 {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
|
|
||||||
belInstancer.parentTo(modelXform);
|
|
||||||
|
|
||||||
auto belMaterial = belScene.createNode("quickMaterial",
|
auto belMaterial = belScene.createNode("quickMaterial",
|
||||||
canonicalName + dl::String("vmaxMat") + dl::String(material) + dl::String("Color") + dl::String(color));
|
canonicalName + dl::String("vmaxMat") + dl::String(material) + dl::String("Color") + dl::String(color));
|
||||||
|
bool isMesh = false;
|
||||||
|
bool isBox = true;
|
||||||
|
|
||||||
if(material==7) {
|
if(material==7) {
|
||||||
belMaterial["type"] = "liquid";
|
belMaterial["type"] = "liquid";
|
||||||
//belMaterial["roughness"] = vmaxMaterial[material].roughness * 100.0f;
|
//belMaterial["roughness"] = vmaxMaterial[material].roughness * 100.0f;
|
||||||
belMaterial["liquidDepth"] = 100.0f;
|
belMaterial["liquidDepth"] = 300.0f;
|
||||||
belMaterial["ior"] = 1.11f;
|
belMaterial["liquidIor"] = 1.33f;
|
||||||
|
isMesh = true;
|
||||||
|
isBox = false;
|
||||||
} else if(material==6 || vmaxPalette[color-1].a < 255) {
|
} else if(material==6 || vmaxPalette[color-1].a < 255) {
|
||||||
belMaterial["type"] = "glass";
|
belMaterial["type"] = "glass";
|
||||||
belMaterial["roughness"] = vmaxMaterial[material].roughness * 100.0f;
|
belMaterial["roughness"] = vmaxMaterial[material].roughness * 100.0f;
|
||||||
belMaterial["glassDepth"] = 200.0f;
|
belMaterial["glassDepth"] = 500.0f;
|
||||||
} else if(vmaxMaterial[material].metalness > 0.1f) {
|
} else if(vmaxMaterial[material].metalness > 0.1f) {
|
||||||
belMaterial["type"] = "metal";
|
belMaterial["type"] = "metal";
|
||||||
belMaterial["roughness"] = vmaxMaterial[material].roughness * 100.0f;
|
belMaterial["roughness"] = vmaxMaterial[material].roughness * 100.0f;
|
||||||
@ -606,7 +617,15 @@ dl::bella_sdk::Node addModelToScene(dl::bella_sdk::Scene& belScene, dl::bella_sd
|
|||||||
belMaterial["type"] = "plastic";
|
belMaterial["type"] = "plastic";
|
||||||
belMaterial["roughness"] = vmaxMaterial[material].roughness * 100.0f;
|
belMaterial["roughness"] = vmaxMaterial[material].roughness * 100.0f;
|
||||||
}
|
}
|
||||||
belInstancer["material"] = belMaterial;
|
|
||||||
|
if (args.have("bevel")) {
|
||||||
|
belMaterial["bevel"] = belBevel;
|
||||||
|
}
|
||||||
|
if (args.have("mode") && args.value("mode") == "mesh" || args.value("mode") == "both") {
|
||||||
|
isMesh = true;
|
||||||
|
isBox = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Convert 0-255 to 0-1 , remember to -1 color index becuase voxelmax needs 0 to indicate no voxel
|
// Convert 0-255 to 0-1 , remember to -1 color index becuase voxelmax needs 0 to indicate no voxel
|
||||||
double bellaR = static_cast<double>(vmaxPalette[color-1].r)/255.0;
|
double bellaR = static_cast<double>(vmaxPalette[color-1].r)/255.0;
|
||||||
double bellaG = static_cast<double>(vmaxPalette[color-1].g)/255.0;
|
double bellaG = static_cast<double>(vmaxPalette[color-1].g)/255.0;
|
||||||
@ -623,32 +642,68 @@ dl::bella_sdk::Node addModelToScene(dl::bella_sdk::Scene& belScene, dl::bella_sd
|
|||||||
const std::vector<VmaxVoxel>& voxelsOfType = vmaxModel.getVoxels(material, color);
|
const std::vector<VmaxVoxel>& voxelsOfType = vmaxModel.getVoxels(material, color);
|
||||||
int showchunk =0;
|
int showchunk =0;
|
||||||
|
|
||||||
// Right now we group voxels by MatCol ie Mat0Col2
|
if (isMesh) {
|
||||||
// But voxels are stored in chunks with many colors
|
auto belMeshXform = belScene.createNode("xform",
|
||||||
// Since we aren't grouping voxels in chunks, we need to traverse the voxels
|
thisname+dl::String("Xform"));
|
||||||
// and offset each voxel by the morton decode of chunk index
|
belMeshXform.parentTo(modelXform);
|
||||||
for (const auto& eachvoxel : voxelsOfType) {
|
|
||||||
// Get chunk coordinates and world origin
|
std::cout << "Converting voxels to mesh\n";
|
||||||
uint32_t _tempx, _tempy, _tempz;
|
// Convert voxels of a particular color to ogt_vox_model
|
||||||
decodeMorton3DOptimized(eachvoxel.chunkID, _tempx, _tempy, _tempz); // index IS the morton code
|
ogt_vox_model* ogt_model = convert_voxelsoftype_to_ogt_vox(voxelsOfType);
|
||||||
int worldOffsetX = _tempx * 24; // get world loc within 256x256x256 grid
|
ogt_mesh_rgba* palette = new ogt_mesh_rgba[256]; // Create a palette array
|
||||||
int worldOffsetY = _tempy * 24; // Don't know why we need to multiply by 24
|
for (int i = 0; i < 256; i++) { // Copy palette from Vmax to OGT
|
||||||
int worldOffsetZ = _tempz * 24; // use to be 32
|
palette[i] = ogt_mesh_rgba{vmaxPalette[i].r, vmaxPalette[i].g, vmaxPalette[i].b, vmaxPalette[i].a};
|
||||||
xformsArray.push_back( dl::Mat4f{ 1, 0, 0, 0,
|
}
|
||||||
|
ogt_voxel_meshify_context ctx = {}; // Create a context struct, not a pointer, todo , what is this for
|
||||||
|
|
||||||
|
// Convert ogt voxels to mesh
|
||||||
|
ogt_mesh* mesh = ogt_mesh_from_paletted_voxels_simple( &ctx,
|
||||||
|
ogt_model->voxel_data,
|
||||||
|
ogt_model->size_x,
|
||||||
|
ogt_model->size_y,
|
||||||
|
ogt_model->size_z,
|
||||||
|
palette );
|
||||||
|
|
||||||
|
if (voxelsOfType.size() > 0) {
|
||||||
|
auto belMesh = add_ogt_mesh_to_scene( thisname,
|
||||||
|
mesh,
|
||||||
|
belScene,
|
||||||
|
belWorld
|
||||||
|
);
|
||||||
|
belMesh.parentTo(belMeshXform);
|
||||||
|
belMeshXform["material"] = belMaterial;
|
||||||
|
} else {
|
||||||
|
std::cout << "skipping" << color << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isBox) {
|
||||||
|
auto belInstancer = belScene.createNode("instancer",
|
||||||
|
thisname);
|
||||||
|
auto xformsArray = dl::ds::Vector<dl::Mat4f>();
|
||||||
|
belInstancer["steps"][0]["xform"] = dl::Mat4 {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
|
||||||
|
belInstancer.parentTo(modelXform);
|
||||||
|
|
||||||
|
std::cout << "Converting voxels to bella boxes\n";
|
||||||
|
//WARNING we use to do morton decoding above but now VoxModel does it when addVoxel is called
|
||||||
|
// So we can just use the x,y,z values
|
||||||
|
for (const auto& eachvoxel : voxelsOfType) {
|
||||||
|
xformsArray.push_back( dl::Mat4f{ 1, 0, 0, 0,
|
||||||
0, 1, 0, 0,
|
0, 1, 0, 0,
|
||||||
0, 0, 1, 0,
|
0, 0, 1, 0,
|
||||||
static_cast<float>(eachvoxel.x + worldOffsetX),
|
(static_cast<float>(eachvoxel.x))+0.5f, // offset center of voxel to match mesh
|
||||||
static_cast<float>(eachvoxel.y + worldOffsetY),
|
(static_cast<float>(eachvoxel.y))+0.5f,
|
||||||
static_cast<float>(eachvoxel.z + worldOffsetZ), 1 });
|
(static_cast<float>(eachvoxel.z))+0.5f, 1 });
|
||||||
}
|
};
|
||||||
belInstancer["steps"][0]["instances"] = xformsArray;
|
belInstancer["steps"][0]["instances"] = xformsArray;
|
||||||
if(material==7) {
|
belInstancer["material"] = belMaterial;
|
||||||
belLiqVoxel.parentTo(belInstancer);
|
if(material==7) {
|
||||||
} else {
|
belLiqVoxel.parentTo(belInstancer);
|
||||||
belMeshVoxel.parentTo(belInstancer);
|
} else {
|
||||||
}
|
belMeshVoxel.parentTo(belInstancer);
|
||||||
if(vmaxMaterial[material].emission > 0.0f) {
|
}
|
||||||
belVoxelForm.parentTo(belInstancer);
|
if(vmaxMaterial[material].emission > 0.0f) {
|
||||||
|
belVoxelForm.parentTo(belInstancer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -656,3 +711,38 @@ dl::bella_sdk::Node addModelToScene(dl::bella_sdk::Scene& belScene, dl::bella_sd
|
|||||||
}
|
}
|
||||||
return dl::bella_sdk::Node();
|
return dl::bella_sdk::Node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dl::bella_sdk::Node add_ogt_mesh_to_scene(dl::String name, ogt_mesh* meshmesh, dl::bella_sdk::Scene& belScene, dl::bella_sdk::Node& belWorld ) {
|
||||||
|
|
||||||
|
//auto ogtXform = belScene.createNode("xform", name+"ogtXform", name+"ogtXform");
|
||||||
|
//ogtXform["steps"][0]["xform"] = dl::Mat4 {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
|
||||||
|
//ogtXform.parentTo(belWorld);
|
||||||
|
auto ogtMesh = belScene.createNode("mesh", name+"ogtmesh", name+"ogtmesh");
|
||||||
|
ogtMesh["normals"] = "flat";
|
||||||
|
// Add vertices and faces to the mesh
|
||||||
|
dl::ds::Vector<dl::Pos3f> verticesArray;
|
||||||
|
for (uint32_t i = 0; i < meshmesh->vertex_count; i++) {
|
||||||
|
const auto& vertex = meshmesh->vertices[i];
|
||||||
|
uint32_t xx = static_cast<uint32_t>(vertex.pos.x);
|
||||||
|
uint32_t yy = static_cast<uint32_t>(vertex.pos.y);
|
||||||
|
uint32_t zz = static_cast<uint32_t>(vertex.pos.z);
|
||||||
|
verticesArray.push_back(dl::Pos3f{ static_cast<float>(xx),
|
||||||
|
static_cast<float>(yy),
|
||||||
|
static_cast<float>(zz) });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ogtMesh["steps"][0]["points"] = verticesArray;
|
||||||
|
|
||||||
|
|
||||||
|
dl::ds::Vector<dl::Vec4u> facesArray;
|
||||||
|
for (size_t i = 0; i < meshmesh->index_count; i+=3) {
|
||||||
|
facesArray.push_back(dl::Vec4u{ static_cast<unsigned int>(meshmesh->indices[i]),
|
||||||
|
static_cast<unsigned int>(meshmesh->indices[i+1]),
|
||||||
|
static_cast<unsigned int>(meshmesh->indices[i+2]),
|
||||||
|
static_cast<unsigned int>(meshmesh->indices[i+2]) });
|
||||||
|
}
|
||||||
|
ogtMesh["polygons"] = facesArray;
|
||||||
|
|
||||||
|
return ogtMesh;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user