You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

247 lines
8.7 KiB

// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2021 Intel Corporation. All Rights Reserved.
#include <iostream>
#include <string>
#include <string.h> // memcpy
#include <fstream>
#include <vector>
#include <tclap/CmdLine.h>
#include <lz4.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#define RS_EMBED_VERSION "0.0.0.2"
struct float3
{
float x, y, z;
};
struct short3
{
uint16_t x, y, z;
};
using namespace std;
using namespace TCLAP;
bool file_exists(const std::string& name) {
std::ifstream f(name.c_str());
return f.good();
}
struct int6
{
int x, y, z, a, b, c;
};
bool ends_with(const std::string& s, const std::string& suffix)
{
auto i = s.rbegin(), j = suffix.rbegin();
for (; i != s.rend() && j != suffix.rend() && *i == *j;
i++, j++);
return j == suffix.rend();
}
std::string get_current_time()
{
auto t = time(nullptr);
char buffer[20] = {};
const tm* time = localtime(&t);
if (nullptr != time)
strftime(buffer, sizeof(buffer), "%m/%d/%Y %H:%M:%S", time);
return std::string(buffer);
}
std::string get_current_year()
{
auto t = time(nullptr);
char buffer[20] = {};
const tm* time = localtime(&t);
if (nullptr != time)
strftime(buffer, sizeof(buffer), "%Y", time);
return std::string(buffer);
}
int main(int argc, char** argv) try
{
// Parse command line arguments
CmdLine cmd("librealsense rs-embed tool", ' ', RS_EMBED_VERSION);
ValueArg<string> inputFilename("i", "input", "Input filename", true, "", "input-file");
ValueArg<string> outputFilename("o", "output", "Output filename", false, "", "output-file");
ValueArg<string> objectName("n", "name", "Name", false, "", "object-name");
cmd.add(inputFilename);
cmd.add(outputFilename);
cmd.add(objectName);
cmd.parse(argc, argv);
auto input = inputFilename.getValue();
auto output = outputFilename.getValue();
auto name = objectName.getValue();
if (ends_with(input, ".obj"))
{
std::vector<float3> vertex_data;
std::vector<float3> normals_raw_data;
std::vector<float3> normals_data;
std::vector<int6> index_raw_data;
std::vector<short3> index_data;
if (file_exists(input))
{
std::ifstream file(input);
std::string str;
while (std::getline(file, str))
{
if (str.size())
{
if (str[0] == 'v')
{
float a, b, c;
if (str[1] == 'n')
{
sscanf(str.c_str(), "vn %f %f %f", &a, &b, &c);
normals_raw_data.push_back({ a, b, c });
}
else
{
sscanf(str.c_str(), "v %f %f %f", &a, &b, &c);
vertex_data.push_back({ a, b, c });
}
}
if (str[0] == 'f')
{
int x, y, z, a, b, c;
sscanf(str.c_str(), "f %d//%d %d//%d %d//%d", &x, &a, &y, &b, &z, &c);
index_raw_data.push_back({ x, y, z, a, b, c });
}
}
}
}
else
{
std::cout << "file: " << input << " could not be found!" << std::endl;
return EXIT_FAILURE;
}
normals_data.resize(vertex_data.size());
for (auto& idx : index_raw_data)
{
// TODO - normals data are currently disabled
// normals_data[idx.x] = normals_raw_data[idx.a];
// normals_data[idx.y] = normals_raw_data[idx.b];
// normals_data[idx.z] = normals_raw_data[idx.c];
index_data.push_back({ static_cast<uint16_t>(idx.x - 1),
static_cast<uint16_t>(idx.y - 1),
static_cast<uint16_t>(idx.z - 1) });
}
size_t vertex_data_size = vertex_data.size() * sizeof(float3);
size_t index_data_size = index_data.size() * sizeof(short3);
//size_t normals_data_size = normals_data.size() * sizeof(float3);
std::vector<uint8_t> data(vertex_data_size + index_data_size, 0);
memcpy(data.data(), vertex_data.data(), vertex_data_size);
memcpy(data.data() + vertex_data_size, index_data.data(), index_data_size);
//memcpy(data.data() + vertex_data_size + index_data_size, normals_data.data(), normals_data_size);
// compress szSource into pchCompressed
auto rawDataSize = (int)data.size();
auto compressBufSize = LZ4_compressBound(rawDataSize);
auto four_byte_mul_size = compressBufSize + ( 4 - compressBufSize % 4 );
char * pchCompressed = new char[four_byte_mul_size];
memset( pchCompressed, 0, four_byte_mul_size );
int nCompressedSize = LZ4_compress_default((const char*)data.data(), pchCompressed, rawDataSize, compressBufSize);
ofstream myfile;
myfile.open(output);
myfile << "// License: Apache 2.0. See LICENSE file in root directory.\n";
myfile << "// Copyright(c) " << get_current_year() << " Intel Corporation. All Rights Reserved.\n\n";
myfile << "// This file is auto-generated from " << name << ".obj using rs-embed tool version: " << RS_EMBED_VERSION <<"\n";
myfile << "// Generation time: " << get_current_time() << ".\n\n";
myfile << "#pragma once\n";
myfile << "static uint32_t " << name << "_obj_data [] { ";
auto nAllignedCompressedSize = nCompressedSize;
auto leftover = nCompressedSize % 4;
nAllignedCompressedSize += (4 - leftover);
for (int i = 0; i < nAllignedCompressedSize; i += 4)
{
uint32_t* ptr = (uint32_t*)(pchCompressed + i);
myfile << "0x" << std::hex << (int)(*ptr);
if (i < nAllignedCompressedSize - 1) myfile << ",";
}
myfile << "};\n";
myfile << "#include <lz4.h>\n";
myfile << "#include <vector>\n";
myfile << "inline void uncompress_" << name << "_obj(std::vector<float3>& vertex_data, std::vector<float3>& normals, std::vector<short3>& index_data)\n";
myfile << "{\n";
myfile << " std::vector<char> uncompressed(0x" << std::hex << rawDataSize << ", 0);\n";
myfile << " (void)LZ4_decompress_safe((const char*)" << name << "_obj_data, uncompressed.data(), 0x" << std::hex << nCompressedSize << ", 0x" << std::hex << rawDataSize << ");\n";
myfile << " const int vertex_size = 0x" << std::hex << vertex_data.size() << " * sizeof(float3);\n";
myfile << " const int index_size = 0x" << std::hex << index_data.size() << " * sizeof(short3);\n";
myfile << " vertex_data.resize(0x" << std::hex << vertex_data.size() << ");\n";
myfile << " memcpy(vertex_data.data(), uncompressed.data(), vertex_size);\n";
myfile << " index_data.resize(0x" << std::hex << index_data.size() << ");\n";
myfile << " memcpy(index_data.data(), uncompressed.data() + vertex_size, index_size);\n";
myfile << " //normals.resize(0x" << std::hex << vertex_data.size() << ");\n";
myfile << " //memcpy(normals.data(), uncompressed.data() + vertex_size + index_size, vertex_size);\n";
myfile << "}\n";
myfile.close();
}
if (ends_with(input, ".png"))
{
ifstream ifs(input, ios::binary | ios::ate);
ifstream::pos_type pos = ifs.tellg();
std::vector<char> buffer(pos);
ifs.seekg(0, ios::beg);
ifs.read(&buffer[0], pos);
ofstream myfile;
myfile.open(output);
myfile << "// License: Apache 2.0. See LICENSE file in root directory.\n";
myfile << "// Copyright(c) " << get_current_year() << " Intel Corporation. All Rights Reserved.\n\n";
myfile << "// This file is auto-generated from " << name << ".png using rs-embed tool version: " << RS_EMBED_VERSION << "\n";
myfile << "// Generation time: " << get_current_time() << ".\n\n";
myfile << "static uint32_t " << name << "_png_size = 0x" << std::hex << buffer.size() << ";\n";
myfile << "static uint8_t " << name << "_png_data [] { ";
for (int i = 0; i < buffer.size(); i++)
{
uint8_t byte = buffer[i];
myfile << "0x" << std::hex << (int)byte;
if (i < buffer.size() - 1) myfile << ",";
}
myfile << "};\n";
myfile.close();
}
return EXIT_SUCCESS;
}
catch (const exception& e)
{
cerr << e.what() << endl;
return EXIT_FAILURE;
}
catch (...)
{
cerr << "some error" << endl;
return EXIT_FAILURE;
}