mirror of
https://github.com/izzy2lost/Diddy-Kong-Racing.git
synced 2026-06-19 01:16:26 -07:00
DKR Assets Tool v0.5.1, finished up .obj model support (#584)
* Assets Revision 0.5.1, finish up OBJ support * Made wrap the default texture wrap mode. Clamping can be done through a .json file * fixed out_of_range issue with getting multiple textures. * Fixed issue with thwomp test model. * Removed unused problematic code from fileHelper * Why did I add an error here? That was dumb. * Updated json lib to latest version to fix issue on mac.
This commit is contained in:
@@ -410,7 +410,7 @@ endif
|
||||
|
||||
build_assets:
|
||||
$(info Building Assets...)
|
||||
$(TOOLS_DIR)/dkr_assets_tool build -o $(ASSETS_OUTPUT) -dkrv $(REGION).$(VERSION) $(MODDED_ARG) >&2 || echo FAIL
|
||||
@$(TOOLS_DIR)/dkr_assets_tool build -o $(ASSETS_OUTPUT) -dkrv $(REGION).$(VERSION) $(MODDED_ARG) >&2 || echo FAIL
|
||||
|
||||
###############################
|
||||
|
||||
@@ -447,11 +447,6 @@ $(BUILD_DIR)/%.s.o: %.s | build_assets
|
||||
$(call print,Assembling:,$<,$@)
|
||||
$(V)$(AS) $(ASFLAGS) -MD $(BUILD_DIR)/$*.d -o $@ $<
|
||||
|
||||
# Specifically override the assets bin output location to match what splat output to the ld file.
|
||||
$(BUILD_DIR)/asm/assets/assets.s.o: asm/assets/assets.s | build_assets
|
||||
$(call print,Assembling Assets:,$<,$@)
|
||||
$(V)$(AS) $(ASFLAGS) -o $(BUILD_DIR)/assets/assets.bin.o $<
|
||||
|
||||
# Specifically override the header file from what splat extracted to be replaced by what we have in the hasm folder
|
||||
$(BUILD_DIR)/asm/header.s.o: src/hasm/header.s | build_assets
|
||||
$(call print,Assembling Header:,$<,$@)
|
||||
|
||||
@@ -6,69 +6,6 @@
|
||||
|
||||
using namespace DkrAssetsTool;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
BuildInfoContext::BuildInfoContext(CContext &cContext, BuildStats &stats, BuildInfoCollection &collection)
|
||||
: _cContext(cContext), _stats(stats), _collection(collection) {}
|
||||
|
||||
CContext &BuildInfoContext::get_c_context() const {
|
||||
return _cContext;
|
||||
}
|
||||
|
||||
BuildStats &BuildInfoContext::get_stats() const {
|
||||
return _stats;
|
||||
}
|
||||
|
||||
BuildInfoCollection &BuildInfoContext::get_collection() const {
|
||||
return _collection;
|
||||
}
|
||||
|
||||
void BuildInfoContext::init_obj_beh_to_entry_map() {
|
||||
if(!_objBehaviorToEntry.empty()) {
|
||||
return; // Don't redo this if the map is already filled!
|
||||
}
|
||||
|
||||
// TODO: This was copy-pasted from extract/config.cpp; need to refactor to not require the config file.
|
||||
|
||||
fs::path pathToConfig = GlobalSettings::get_decomp_path("tools", "tools/") / "dkr_assets_tool_extract.json";
|
||||
auto tryGetConfigFile = JsonHelper::get_file(pathToConfig);
|
||||
DebugHelper::assert_(tryGetConfigFile.has_value(),
|
||||
"(BuildInfoContext::init_obj_beh_to_entry_map) Could not find the config file at: ", pathToConfig);
|
||||
JsonFile &configJson = tryGetConfigFile.value();
|
||||
|
||||
CContext &cContext = get_c_context();
|
||||
|
||||
CEnum *objBehaviors = cContext.get_enum("ObjectBehaviours");
|
||||
|
||||
DebugHelper::assert_(objBehaviors != nullptr,
|
||||
"(BuildInfoContext::init_obj_beh_to_entry_map) The enum ObjectBehaviours could not be loaded!");
|
||||
|
||||
std::vector<std::string> defaultObjEntriesOrder;
|
||||
configJson.get_array<std::string>("/misc/default-object-entries-order", defaultObjEntriesOrder);
|
||||
|
||||
for(int i = 0; i < 128; i++) {
|
||||
std::string symbol;
|
||||
DebugHelper::assert_(objBehaviors->get_symbol_of_value(i, symbol),
|
||||
"(BuildInfoContext::init_obj_beh_to_entry_map) Could not get a symbol for the value ", i, " in the ObjectBehaviors enum.");
|
||||
|
||||
CStruct *entryStruct = cContext.get_struct(defaultObjEntriesOrder[i]);
|
||||
DebugHelper::assert_(entryStruct != nullptr,
|
||||
"(BuildInfoContext::init_obj_beh_to_entry_map) Could not find struct \"", defaultObjEntriesOrder[i], "\"");
|
||||
|
||||
_objBehaviorToEntry[symbol] = defaultObjEntriesOrder[i];
|
||||
}
|
||||
}
|
||||
|
||||
std::string BuildInfoContext::get_object_entry_from_behavior(std::string objBehavior) const {
|
||||
DebugHelper::assert_(_objBehaviorToEntry.find(objBehavior) != _objBehaviorToEntry.end(),
|
||||
"(AssetExtractConfig::get_object_entry_from_behavior) ", objBehavior,
|
||||
" was not in the _objBehaviorToEntry map!");
|
||||
|
||||
return _objBehaviorToEntry.at(objBehavior);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
BuildInfo::BuildInfo() {
|
||||
DebugHelper::error("Must not initalize empty build info.");
|
||||
}
|
||||
@@ -85,15 +22,15 @@ BuildInfo::BuildInfo(JsonFile *src, const fs::path &dir)
|
||||
}
|
||||
*/
|
||||
|
||||
BuildInfo::BuildInfo(std::string buildId, const JsonFile &src, size_t fileIndex, const fs::path &dir, const BuildInfoContext &infoContext)
|
||||
: _dstPath(""), _localDirectory(dir), _jsonFile(src), _infoContext(infoContext), _buildId(buildId), _fileIndex(fileIndex) {
|
||||
BuildInfo::BuildInfo(std::string buildId, std::string buildSectionId, const JsonFile &src, size_t fileIndex, const fs::path &dir, const BuildInfoContext &infoContext)
|
||||
: _dstPath(""), _localDirectory(dir), _jsonFile(src), _infoContext(infoContext), _buildId(buildId), _buildSectionId(buildSectionId), _fileIndex(fileIndex) {
|
||||
_buildType = BUILD_TO_BINARY;
|
||||
const JsonFile &jsonFile = get_src_json_file();
|
||||
_type = jsonFile.get_string("/type", "NoType");
|
||||
}
|
||||
|
||||
BuildInfo::BuildInfo(std::string buildId, const std::vector<uint8_t> &outData, size_t fileIndex, const fs::path &dir, const BuildInfoContext &infoContext)
|
||||
: out(outData), _dstPath(""), _localDirectory(dir), _jsonFile(std::nullopt), _infoContext(infoContext), _buildId(buildId), _type("Binary"), _fileIndex(fileIndex) {
|
||||
BuildInfo::BuildInfo(std::string buildId, std::string buildSectionId, const std::vector<uint8_t> &outData, size_t fileIndex, const fs::path &dir, const BuildInfoContext &infoContext)
|
||||
: out(outData), _dstPath(""), _localDirectory(dir), _jsonFile(std::nullopt), _infoContext(infoContext), _buildId(buildId), _buildSectionId(buildSectionId), _type("Binary"), _fileIndex(fileIndex) {
|
||||
_buildType = BUILD_TO_BINARY;
|
||||
}
|
||||
|
||||
@@ -145,11 +82,11 @@ CContext &BuildInfo::get_c_context() const {
|
||||
return infoContext.get_c_context();
|
||||
}
|
||||
|
||||
BuildStats &BuildInfo::get_stats() const {
|
||||
BuildTextureCache &BuildInfo::get_texture_cache() const {
|
||||
const BuildInfoContext &infoContext = _infoContext.value();
|
||||
return infoContext.get_stats();
|
||||
return infoContext.get_texture_cache();
|
||||
}
|
||||
|
||||
|
||||
BuildInfoCollection &BuildInfo::get_collection() const {
|
||||
const BuildInfoContext &infoContext = _infoContext.value();
|
||||
return infoContext.get_collection();
|
||||
@@ -175,6 +112,10 @@ std::string BuildInfo::get_build_id() const {
|
||||
return _buildId;
|
||||
}
|
||||
|
||||
std::string BuildInfo::get_section_build_id() const {
|
||||
return _buildSectionId;
|
||||
}
|
||||
|
||||
size_t BuildInfo::get_file_index() const {
|
||||
return _fileIndex;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "helpers/jsonHelper.h"
|
||||
#include "helpers/c/cContext.h"
|
||||
|
||||
#include "builder/buildInfoContext.h"
|
||||
|
||||
namespace DkrAssetsTool {
|
||||
|
||||
typedef enum BuildInfoType {
|
||||
@@ -17,38 +19,17 @@ typedef enum BuildInfoType {
|
||||
BUILD_TO_BINARY // When building all assets
|
||||
} BuildInfoType;
|
||||
|
||||
class BuildStats;
|
||||
class BuildInfoCollection;
|
||||
|
||||
class BuildInfoContext {
|
||||
public:
|
||||
BuildInfoContext(CContext &cContext, BuildStats &stats, BuildInfoCollection &collection);
|
||||
|
||||
CContext &get_c_context() const;
|
||||
BuildStats &get_stats() const;
|
||||
BuildInfoCollection &get_collection() const;
|
||||
|
||||
// Used in BuildObjectMap
|
||||
void init_obj_beh_to_entry_map();
|
||||
std::string get_object_entry_from_behavior(std::string objBehavior) const;
|
||||
private:
|
||||
std::reference_wrapper<CContext> _cContext;
|
||||
std::reference_wrapper<BuildStats> _stats;
|
||||
std::reference_wrapper<BuildInfoCollection> _collection;
|
||||
|
||||
std::unordered_map<std::string, std::string> _objBehaviorToEntry;
|
||||
};
|
||||
|
||||
class BuildInfo {
|
||||
public:
|
||||
BuildInfo();
|
||||
//BuildInfo(std::string buildId, JsonFile *src, const fs::path &dst, const fs::path &dir); // BUILD_TO_FILE, TODO
|
||||
//BuildInfo(std::string buildId, JsonFile *src, const fs::path &dir); // BUILD_TO_BINARY
|
||||
BuildInfo(std::string buildId, const JsonFile &src, size_t fileIndex, const fs::path &dir, const BuildInfoContext &infoContext); // BUILD_TO_BINARY
|
||||
BuildInfo(std::string buildId, const std::vector<uint8_t> &outData, size_t fileIndex, const fs::path &dir, const BuildInfoContext &infoContext); // BUILD_TO_BINARY
|
||||
BuildInfo(std::string buildId, std::string buildSectionId, const JsonFile &src, size_t fileIndex, const fs::path &dir, const BuildInfoContext &infoContext);
|
||||
BuildInfo(std::string buildId, std::string buildSectionId, const std::vector<uint8_t> &outData, size_t fileIndex, const fs::path &dir, const BuildInfoContext &infoContext);
|
||||
~BuildInfo();
|
||||
|
||||
//JsonFile *srcFile; // Deprecated!
|
||||
std::vector<uint8_t> out;
|
||||
|
||||
BuildInfoType get_build_type() const;
|
||||
@@ -63,14 +44,10 @@ public:
|
||||
fs::path get_dst_folder() const;
|
||||
fs::path get_dst_filename() const;
|
||||
|
||||
//void set_c_context(CContext &cContext);
|
||||
//void set_stats(BuildStats &stats);
|
||||
//void set_collection(BuildInfoCollection &collection);
|
||||
|
||||
fs::path get_path_to_directory() const;
|
||||
|
||||
CContext &get_c_context() const;
|
||||
BuildStats &get_stats() const;
|
||||
BuildTextureCache &get_texture_cache() const;
|
||||
BuildInfoCollection &get_collection() const;
|
||||
|
||||
const JsonFile &get_src_json_file() const;
|
||||
@@ -78,6 +55,7 @@ public:
|
||||
|
||||
std::string get_type() const;
|
||||
std::string get_build_id() const;
|
||||
std::string get_section_build_id() const;
|
||||
size_t get_file_index() const;
|
||||
|
||||
bool is_complete() const;
|
||||
@@ -96,6 +74,7 @@ private:
|
||||
std::optional<std::reference_wrapper<const BuildInfoContext>> _infoContext;
|
||||
|
||||
std::string _buildId;
|
||||
std::string _buildSectionId;
|
||||
std::string _type;
|
||||
size_t _fileIndex;
|
||||
BuildInfoType _buildType;
|
||||
|
||||
@@ -38,7 +38,7 @@ void BuildInfoCollection::add_build_info(std::string sectionBuildId, std::string
|
||||
"(BuildInfoCollection::add_build_info) Max number of assets reached! Limit was ", MAX_NUMBER_OF_BUILD_INFOS);
|
||||
|
||||
size_t fileIndex = _buildInfoSections[sectionBuildId].size();
|
||||
_buildInfos.emplace_back(buildId, src, fileIndex, dir, infoContext);
|
||||
_buildInfos.emplace_back(buildId, sectionBuildId, src, fileIndex, dir, infoContext);
|
||||
|
||||
// Add the index to the section.
|
||||
_buildInfoSections[sectionBuildId].emplace_back(index);
|
||||
@@ -59,7 +59,7 @@ size_t BuildInfoCollection::add_deferred_build_info(std::string sectionBuildId,
|
||||
"(BuildInfoCollection::add_build_info) Max number of assets reached! Limit was ", MAX_NUMBER_OF_BUILD_INFOS);
|
||||
|
||||
size_t fileIndex = _buildInfoSections[sectionBuildId].size();
|
||||
_buildInfos.emplace_back(buildId, out, fileIndex, dir, infoContext);
|
||||
_buildInfos.emplace_back(buildId, sectionBuildId, out, fileIndex, dir, infoContext);
|
||||
|
||||
// Do not process deferred assets.
|
||||
_buildInfos.back().done();
|
||||
@@ -89,7 +89,7 @@ void BuildInfoCollection::add_deferred_build_info(std::string sectionBuildId, st
|
||||
DebugHelper::assert_(index < MAX_NUMBER_OF_BUILD_INFOS,
|
||||
"(BuildInfoCollection::add_build_info) Max number of assets reached! Limit was ", MAX_NUMBER_OF_BUILD_INFOS);
|
||||
|
||||
_buildInfos.emplace_back(buildId, out, fileIndex, dir, infoContext);
|
||||
_buildInfos.emplace_back(buildId, sectionBuildId, out, fileIndex, dir, infoContext);
|
||||
|
||||
// Do not process deferred assets.
|
||||
_buildInfos.back().done();
|
||||
@@ -100,7 +100,7 @@ void BuildInfoCollection::add_deferred_build_info(std::string sectionBuildId, st
|
||||
_buildInfoMutex.unlock();
|
||||
}
|
||||
|
||||
void BuildInfoCollection::run_builds(std::function<void(BuildInfo &)> callbackFunction) {
|
||||
void BuildInfoCollection::run_builds(std::function<void(BuildInfo &)> callbackFunction, const std::vector<std::string> §ionsOrder) {
|
||||
size_t threadCount = GlobalSettings::get_max_thread_count();
|
||||
bool multithreaded = threadCount != 1;
|
||||
DebugHelper::info_verbose("Using ", threadCount, " thread", (multithreaded ? "s" : ""));
|
||||
@@ -108,8 +108,12 @@ void BuildInfoCollection::run_builds(std::function<void(BuildInfo &)> callbackFu
|
||||
if(multithreaded) {
|
||||
// Multi-threaded (Better for performance)
|
||||
ThreadPool pool(threadCount);
|
||||
for(auto &pair : _buildInfoSections) {
|
||||
for(int buildInfoIndex : pair.second) {
|
||||
for(const std::string §ionBuildId : sectionsOrder) {
|
||||
if(_buildInfoSections.find(sectionBuildId) == _buildInfoSections.end()) {
|
||||
// Skip empty sections.
|
||||
continue;
|
||||
}
|
||||
for(int buildInfoIndex : _buildInfoSections[sectionBuildId]) {
|
||||
BuildInfo &info = _buildInfos[buildInfoIndex];
|
||||
pool.enqueue([&info, &callbackFunction] {
|
||||
if(!info.is_complete()) {
|
||||
@@ -121,8 +125,12 @@ void BuildInfoCollection::run_builds(std::function<void(BuildInfo &)> callbackFu
|
||||
}
|
||||
} else {
|
||||
// Single-threaded (Better for debugging)
|
||||
for(auto &pair : _buildInfoSections) {
|
||||
for(int buildInfoIndex : pair.second) {
|
||||
for(const std::string §ionBuildId : sectionsOrder) {
|
||||
if(_buildInfoSections.find(sectionBuildId) == _buildInfoSections.end()) {
|
||||
// Skip empty sections.
|
||||
continue;
|
||||
}
|
||||
for(int buildInfoIndex : _buildInfoSections[sectionBuildId]) {
|
||||
BuildInfo &info = _buildInfos[buildInfoIndex];
|
||||
if(!info.is_complete()) {
|
||||
callbackFunction(info);
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
void add_deferred_build_info(std::string sectionBuildId, std::string buildId, size_t fileIndex, const std::vector<uint8_t> &out,
|
||||
const fs::path &dir, const BuildInfoContext &infoContext);
|
||||
|
||||
void run_builds(std::function<void(BuildInfo &info)> callbackFunction);
|
||||
void run_builds(std::function<void(BuildInfo &info)> callbackFunction, const std::vector<std::string> §ionsOrder);
|
||||
|
||||
void get_infos_for_section(std::string sectionBuildId, std::function<void(BuildInfo &info)> callbackFunction);
|
||||
|
||||
@@ -49,8 +49,6 @@ private:
|
||||
// Note: Should only ever be added to! Do NOT erase any entries during the building process!
|
||||
std::vector<BuildInfo> _buildInfos;
|
||||
|
||||
std::vector<std::string> _sectionOrder;
|
||||
|
||||
// <key: Section build id, value: Array of indices into _buildInfos for files associated with the section>
|
||||
std::unordered_map<std::string, std::vector<int>> _buildInfoSections;
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "buildInfo.h"
|
||||
|
||||
#include "misc/globalSettings.h"
|
||||
#include "helpers/c/cContext.h"
|
||||
#include "helpers/jsonHelper.h"
|
||||
|
||||
using namespace DkrAssetsTool;
|
||||
|
||||
BuildInfoContext::BuildInfoContext(CContext &cContext, BuildTextureCache &textureCache, BuildInfoCollection &collection)
|
||||
: _cContext(cContext), _textureCache(textureCache), _collection(collection) {}
|
||||
|
||||
CContext &BuildInfoContext::get_c_context() const {
|
||||
return _cContext;
|
||||
}
|
||||
|
||||
BuildTextureCache &BuildInfoContext::get_texture_cache() const {
|
||||
return _textureCache;
|
||||
}
|
||||
|
||||
BuildInfoCollection &BuildInfoContext::get_collection() const {
|
||||
return _collection;
|
||||
}
|
||||
|
||||
void BuildInfoContext::init_obj_beh_to_entry_map() {
|
||||
if(!_objBehaviorToEntry.empty()) {
|
||||
return; // Don't redo this if the map is already filled!
|
||||
}
|
||||
|
||||
// TODO: This was copy-pasted from extract/config.cpp; need to refactor to not require the config file.
|
||||
|
||||
fs::path pathToConfig = GlobalSettings::get_decomp_path("tools", "tools/") / "dkr_assets_tool_extract.json";
|
||||
auto tryGetConfigFile = JsonHelper::get_file(pathToConfig);
|
||||
DebugHelper::assert_(tryGetConfigFile.has_value(),
|
||||
"(BuildInfoContext::init_obj_beh_to_entry_map) Could not find the config file at: ", pathToConfig);
|
||||
JsonFile &configJson = tryGetConfigFile.value();
|
||||
|
||||
CContext &cContext = get_c_context();
|
||||
|
||||
CEnum *objBehaviors = cContext.get_enum("ObjectBehaviours");
|
||||
|
||||
DebugHelper::assert_(objBehaviors != nullptr,
|
||||
"(BuildInfoContext::init_obj_beh_to_entry_map) The enum ObjectBehaviours could not be loaded!");
|
||||
|
||||
std::vector<std::string> defaultObjEntriesOrder;
|
||||
configJson.get_array<std::string>("/misc/default-object-entries-order", defaultObjEntriesOrder);
|
||||
|
||||
for(int i = 0; i < 128; i++) {
|
||||
std::string symbol;
|
||||
DebugHelper::assert_(objBehaviors->get_symbol_of_value(i, symbol),
|
||||
"(BuildInfoContext::init_obj_beh_to_entry_map) Could not get a symbol for the value ", i, " in the ObjectBehaviors enum.");
|
||||
|
||||
CStruct *entryStruct = cContext.get_struct(defaultObjEntriesOrder[i]);
|
||||
DebugHelper::assert_(entryStruct != nullptr,
|
||||
"(BuildInfoContext::init_obj_beh_to_entry_map) Could not find struct \"", defaultObjEntriesOrder[i], "\"");
|
||||
|
||||
_objBehaviorToEntry[symbol] = defaultObjEntriesOrder[i];
|
||||
}
|
||||
}
|
||||
|
||||
std::string BuildInfoContext::get_object_entry_from_behavior(std::string objBehavior) const {
|
||||
DebugHelper::assert_(_objBehaviorToEntry.find(objBehavior) != _objBehaviorToEntry.end(),
|
||||
"(AssetExtractConfig::get_object_entry_from_behavior) ", objBehavior,
|
||||
" was not in the _objBehaviorToEntry map!");
|
||||
|
||||
return _objBehaviorToEntry.at(objBehavior);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <optional>
|
||||
#include <mutex>
|
||||
|
||||
#include "helpers/fileHelper.h"
|
||||
#include "helpers/jsonHelper.h"
|
||||
#include "helpers/c/cContext.h"
|
||||
|
||||
#include "builder/textureCache.h"
|
||||
|
||||
namespace DkrAssetsTool {
|
||||
|
||||
class BuildInfoCollection;
|
||||
|
||||
class BuildInfoContext {
|
||||
public:
|
||||
BuildInfoContext(CContext &cContext, BuildTextureCache &textureCache, BuildInfoCollection &collection);
|
||||
|
||||
CContext &get_c_context() const;
|
||||
BuildTextureCache &get_texture_cache() const;
|
||||
BuildInfoCollection &get_collection() const;
|
||||
|
||||
// Used in BuildObjectMap
|
||||
void init_obj_beh_to_entry_map();
|
||||
std::string get_object_entry_from_behavior(std::string objBehavior) const;
|
||||
|
||||
private:
|
||||
std::reference_wrapper<CContext> _cContext;
|
||||
std::reference_wrapper<BuildTextureCache> _textureCache;
|
||||
std::reference_wrapper<BuildInfoCollection> _collection;
|
||||
|
||||
std::unordered_map<std::string, std::string> _objBehaviorToEntry;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -53,12 +53,16 @@ void BuildModel::generate_object_model(BuildInfo &info) {
|
||||
DkrTriangle *triangles = reinterpret_cast<DkrTriangle *>(&info.out[objectModelHeader->triangles]);
|
||||
DkrBatch *batches = reinterpret_cast<DkrBatch *>(&info.out[objectModelHeader->batches]);
|
||||
|
||||
bool hasAnimatedTexture = false;
|
||||
for(size_t materialIndex = 0; materialIndex < numberOfTextures; materialIndex++) {
|
||||
_materials[materialIndex].write_to(&textures[materialIndex], info);
|
||||
BuildModelMaterial &material = _materials[materialIndex];
|
||||
material.write_to(&textures[materialIndex], info);
|
||||
hasAnimatedTexture = hasAnimatedTexture || material.is_texture_animated();
|
||||
}
|
||||
objectModelHeader->hasAnimatedTexture = (int)hasAnimatedTexture;
|
||||
|
||||
for(auto &block : _blocks) {
|
||||
block.write_batches(_materialIds, batches, vertices, triangles);
|
||||
block.write_batches(_materialIds, _materials, batches, vertices, triangles);
|
||||
}
|
||||
|
||||
bool debugKeepUncompressed = GlobalSettings::get_value<bool>("/debug/keep-uncompressed", false);
|
||||
|
||||
@@ -46,23 +46,39 @@ size_t BuildModelBatch::number_of_vertices() {
|
||||
return _vertices.size();
|
||||
}
|
||||
|
||||
void BuildModelBatch::write_batch(const std::map<std::string, int> &materialIds, DkrBatch* outBatch, DkrVertex*& outVertices, DkrTriangle*& outTriangles) {
|
||||
void BuildModelBatch::write_batch(const std::map<std::string, int> &materialIds, std::vector<BuildModelMaterial> &materials,
|
||||
DkrBatch* outBatch, DkrVertex*& outVertices, DkrTriangle*& outTriangles) {
|
||||
uint32_t flags = 0x00000003;
|
||||
bool materialDoubleSided = false;
|
||||
|
||||
if(_materialId.has_value()) {
|
||||
outBatch->textureIndex = materialIds.at(_materialId.value());
|
||||
BuildModelMaterial &material = materials[outBatch->textureIndex];
|
||||
if(material.is_texture_animated()) {
|
||||
flags |= 0x10000; // BATCH_FLAGS_TEXTURE_ANIM
|
||||
}
|
||||
materialDoubleSided = material.is_texture_double_sided();
|
||||
} else {
|
||||
outBatch->textureIndex = 0xFF; // No texture
|
||||
}
|
||||
|
||||
//outBatch->lightSource = 0; // 0xFF = vertex colors, 0 = Use generated normals.
|
||||
outBatch->flags = 0x00000003; // TODO
|
||||
outBatch->flags = flags;
|
||||
|
||||
bool useVertexColors = false;
|
||||
for(auto &vertex : _vertices) {
|
||||
vertex.write_to(outVertices);
|
||||
outVertices++; // Next out vertex.
|
||||
if(!vertex.is_color_white()) {
|
||||
useVertexColors = true;
|
||||
}
|
||||
}
|
||||
|
||||
outBatch->lightSource = useVertexColors ? 0xFF : 0x00;
|
||||
|
||||
uint8_t triFlags = materialDoubleSided ? 0x40 : 0x00;
|
||||
|
||||
for(auto &tri : _triangles) {
|
||||
outTriangles->flags = 0x40; // double-sided (debug)
|
||||
outTriangles->flags = triFlags;
|
||||
outTriangles->vi0 = tri.a;
|
||||
outTriangles->vi1 = tri.b;
|
||||
outTriangles->vi2 = tri.c;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "helpers/mathHelper.h"
|
||||
|
||||
#include "buildModelVertex.h"
|
||||
#include "buildModelMaterial.h"
|
||||
|
||||
#include "fileTypes/vertex.hpp"
|
||||
#include "fileTypes/triangle.hpp"
|
||||
@@ -35,7 +36,8 @@ public:
|
||||
size_t number_of_triangles();
|
||||
size_t number_of_vertices();
|
||||
|
||||
void write_batch(const std::map<std::string, int> &materialIds, DkrBatch* outBatch, DkrVertex*& outVertices, DkrTriangle*& outTriangles);
|
||||
void write_batch(const std::map<std::string, int> &materialIds, std::vector<BuildModelMaterial> &materials,
|
||||
DkrBatch* outBatch, DkrVertex*& outVertices, DkrTriangle*& outTriangles);
|
||||
|
||||
private:
|
||||
std::vector<BuildModelTriangle> _triangles;
|
||||
|
||||
@@ -61,11 +61,12 @@ size_t BuildModelBlock::number_of_batches_to_allocate() {
|
||||
return _batches.size() + 1; // Must have an extra entry to calculate the sizes for the last batch.
|
||||
}
|
||||
|
||||
void BuildModelBlock::write_batches(const std::map<std::string, int> &materialIds, DkrBatch*& outBatches, DkrVertex*& outVertices, DkrTriangle*& outTriangles) {
|
||||
void BuildModelBlock::write_batches(const std::map<std::string, int> &materialIds, std::vector<BuildModelMaterial> &materials,
|
||||
DkrBatch*& outBatches, DkrVertex*& outVertices, DkrTriangle*& outTriangles) {
|
||||
size_t vertexCount = 0;
|
||||
size_t triCount = 0;
|
||||
for(auto &batch : _batches) {
|
||||
batch.write_batch(materialIds, outBatches, outVertices, outTriangles);
|
||||
batch.write_batch(materialIds, materials, outBatches, outVertices, outTriangles);
|
||||
outBatches->verticesOffset = vertexCount;
|
||||
outBatches->trianglesOffset = triCount;
|
||||
outBatches->unk1 = (int8_t)batch.number_of_vertices();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <map>
|
||||
|
||||
#include "buildModelVertex.h"
|
||||
#include "buildModelMaterial.h"
|
||||
#include "buildModelBatch.h"
|
||||
|
||||
#include "fileTypes/vertex.hpp"
|
||||
@@ -25,7 +26,8 @@ public:
|
||||
size_t number_of_batches();
|
||||
size_t number_of_batches_to_allocate();
|
||||
|
||||
void write_batches(const std::map<std::string, int> &materialIds, DkrBatch*& outBatches, DkrVertex*& outVertices, DkrTriangle*& outTriangles);
|
||||
void write_batches(const std::map<std::string, int> &materialIds, std::vector<BuildModelMaterial> &materials,
|
||||
DkrBatch*& outBatches, DkrVertex*& outVertices, DkrTriangle*& outTriangles);
|
||||
|
||||
private:
|
||||
std::vector<BuildModelBatch> _batches;
|
||||
|
||||
@@ -36,6 +36,26 @@ void BuildModelMaterial::write_to(DkrTextureInfo *outTexInfo, BuildInfo &info) {
|
||||
bool BuildModelMaterial::has_texture() const {
|
||||
return _texturePath.has_value();
|
||||
}
|
||||
|
||||
bool BuildModelMaterial::is_texture_animated() {
|
||||
if(!_texturePath.has_value()) {
|
||||
return false;
|
||||
}
|
||||
if(!_isTextureAnimated.has_value()) {
|
||||
_isTextureAnimated = ImageHelper::guess_if_texture_is_animated(_texturePath.value());
|
||||
}
|
||||
return _isTextureAnimated.value();
|
||||
}
|
||||
|
||||
bool BuildModelMaterial::is_texture_double_sided() {
|
||||
if(!_texturePath.has_value()) {
|
||||
return false;
|
||||
}
|
||||
if(!_isTextureDoubleSided.has_value()) {
|
||||
_isTextureDoubleSided = ImageHelper::guess_if_texture_double_sided(_texturePath.value());
|
||||
}
|
||||
return _isTextureDoubleSided.value();
|
||||
}
|
||||
|
||||
void BuildModelMaterial::get_texture_width_and_height(int &outWidth, int &outHeight) {
|
||||
if(!_texturePath.has_value()) {
|
||||
|
||||
@@ -19,11 +19,15 @@ public:
|
||||
|
||||
std::optional<fs::path> get_texture_path();
|
||||
bool has_texture() const;
|
||||
bool is_texture_animated();
|
||||
bool is_texture_double_sided();
|
||||
|
||||
void get_texture_width_and_height(int &outWidth, int &outHeight);
|
||||
|
||||
private:
|
||||
std::optional<fs::path> _texturePath;
|
||||
std::optional<bool> _isTextureAnimated = std::nullopt;
|
||||
std::optional<bool> _isTextureDoubleSided = std::nullopt;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,10 @@ Vec4f BuildModelVertex::color() const {
|
||||
return _color;
|
||||
}
|
||||
|
||||
bool BuildModelVertex::is_color_white() const {
|
||||
return _color == COLOR_WHITE;
|
||||
}
|
||||
|
||||
void BuildModelVertex::write_to(DkrVertex *outVertex) {
|
||||
// Write position
|
||||
outVertex->x = static_cast<int16_t>(_position.x * 10);
|
||||
|
||||
@@ -26,6 +26,8 @@ public:
|
||||
Vec3f position() const;
|
||||
Vec4f color() const;
|
||||
|
||||
bool is_color_white() const;
|
||||
|
||||
void write_to(DkrVertex *outVertex);
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,10 +1,88 @@
|
||||
#include "objModel.h"
|
||||
|
||||
#include <sstream>
|
||||
#include "helpers/fileHelper.h"
|
||||
#include "helpers/dataHelper.h"
|
||||
#include "helpers/debugHelper.h"
|
||||
|
||||
#include "libs/TriangulatePolygon.hpp"
|
||||
|
||||
using namespace DkrAssetsTool;
|
||||
|
||||
typedef struct ObjFaceComponent {
|
||||
int vertexIndex = -1;
|
||||
int uvIndex = -1;
|
||||
int normalIndex = -1; // Not used in DKR, since normals are generated automatically.
|
||||
} ObjFaceComponent;
|
||||
|
||||
typedef struct ObjTriangle {
|
||||
ObjFaceComponent a;
|
||||
ObjFaceComponent b;
|
||||
ObjFaceComponent c;
|
||||
|
||||
ObjTriangle(ObjFaceComponent newA, ObjFaceComponent newB, ObjFaceComponent newC)
|
||||
: a(newA), b(newB), c(newC) {}
|
||||
} ObjTriangle;
|
||||
|
||||
ObjFaceComponent parse_face_component(std::string component) {
|
||||
std::vector<std::string> faceComponents;
|
||||
StringHelper::split(component, '/', faceComponents);
|
||||
ObjFaceComponent out;
|
||||
|
||||
out.vertexIndex = std::stoi(faceComponents[0]) - 1;
|
||||
|
||||
if((faceComponents.size() > 1) && (!faceComponents[1].empty())) {
|
||||
out.uvIndex = std::stoi(faceComponents[1]) - 1;
|
||||
}
|
||||
|
||||
if((faceComponents.size() > 2) && (!faceComponents[2].empty())) {
|
||||
out.normalIndex = std::stoi(faceComponents[2]) - 1;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<ObjTriangle> triangulate_polygon(const std::vector<std::string> &components, const std::vector<BuildModelVertex> &vertices) {
|
||||
size_t numberOfOutTriangles = components.size() - 3;
|
||||
|
||||
std::vector<ObjTriangle> out;
|
||||
|
||||
if(numberOfOutTriangles == 1) {
|
||||
// No need to triangulate.
|
||||
out.push_back({
|
||||
parse_face_component(components[1]),
|
||||
parse_face_component(components[2]),
|
||||
parse_face_component(components[3])
|
||||
});
|
||||
} else {
|
||||
std::vector<ObjFaceComponent> faceComponents(components.size() - 1);
|
||||
std::vector<triangulate::Point> polygonPoints;
|
||||
|
||||
for(size_t i = 1; i < components.size(); i++) {
|
||||
faceComponents[i - 1] = parse_face_component(components[i]);
|
||||
const BuildModelVertex &vertex = vertices.at(faceComponents[i - 1].vertexIndex);
|
||||
Vec3f vertexPos = vertex.position();
|
||||
polygonPoints.emplace_back(vertexPos.x, vertexPos.y, vertexPos.z);
|
||||
}
|
||||
|
||||
const auto triangles = triangulate::triangulate(polygonPoints);
|
||||
|
||||
for(auto &tri : triangles) {
|
||||
int index0 = DataHelper::vector_index_of(polygonPoints, tri.p0);
|
||||
int index1 = DataHelper::vector_index_of(polygonPoints, tri.p1);
|
||||
int index2 = DataHelper::vector_index_of(polygonPoints, tri.p2);
|
||||
|
||||
DebugHelper::assert_(index0 >= 0, "(triangulate_polygon) Invalid point 0");
|
||||
DebugHelper::assert_(index1 >= 0, "(triangulate_polygon) Invalid point 1");
|
||||
DebugHelper::assert_(index2 >= 0, "(triangulate_polygon) Invalid point 2");
|
||||
|
||||
out.emplace_back(faceComponents[index0], faceComponents[index1], faceComponents[index2]);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
ObjBuildModel::ObjBuildModel(fs::path filepath) {
|
||||
std::string objText = FileHelper::read_text_file(filepath);
|
||||
|
||||
@@ -16,8 +94,6 @@ ObjBuildModel::ObjBuildModel(fs::path filepath) {
|
||||
|
||||
std::string currentMaterial = "";
|
||||
|
||||
size_t faceIndex = 0;
|
||||
|
||||
for(std::string &line : lines) {
|
||||
if(line[0] == '#' || line.empty()) {
|
||||
// Skip this line if it is empty or a comment.
|
||||
@@ -30,15 +106,18 @@ ObjBuildModel::ObjBuildModel(fs::path filepath) {
|
||||
double x = std::stod(components[1]);
|
||||
double y = std::stod(components[2]);
|
||||
double z = std::stod(components[3]);
|
||||
|
||||
// Scale the model according that is specified in settings.
|
||||
//settings.adjust_from_model_scale(x);
|
||||
//settings.adjust_from_model_scale(y);
|
||||
// settings.adjust_from_model_scale(z);
|
||||
|
||||
// Add the new vertex
|
||||
vertices.emplace_back(Vec3f(x, y, z));
|
||||
continue;
|
||||
|
||||
if(components.size() < 6) {
|
||||
// Add the new vertex
|
||||
vertices.emplace_back(Vec3f(x, y, z));
|
||||
continue;
|
||||
}
|
||||
|
||||
double r = std::stod(components[4]);
|
||||
double g = std::stod(components[5]);
|
||||
double b = std::stod(components[6]);
|
||||
vertices.emplace_back(Vec3f(x, y, z), Vec4f(r, g, b, 1.0f));
|
||||
continue;
|
||||
}
|
||||
if(components[0] == "vn") {
|
||||
// User-generated normals are not used in DKR.
|
||||
@@ -52,47 +131,24 @@ ObjBuildModel::ObjBuildModel(fs::path filepath) {
|
||||
continue;
|
||||
}
|
||||
if(components[0] == "f") {
|
||||
std::vector<std::string> faceComponentsA;
|
||||
std::vector<std::string> faceComponentsB;
|
||||
std::vector<std::string> faceComponentsC;
|
||||
std::vector<ObjTriangle> tris = triangulate_polygon(components, vertices);
|
||||
|
||||
// split the different indicies for a face.
|
||||
StringHelper::split(components[1], '/', faceComponentsA);
|
||||
StringHelper::split(components[2], '/', faceComponentsB);
|
||||
StringHelper::split(components[3], '/', faceComponentsC);
|
||||
|
||||
// parse index for vertex.
|
||||
int positionAIndex = std::stoi(faceComponentsA[0]) - 1;
|
||||
int positionBIndex = std::stoi(faceComponentsB[0]) - 1;
|
||||
int positionCIndex = std::stoi(faceComponentsC[0]) - 1;
|
||||
|
||||
// Make sure the indicies are in the correct range.
|
||||
DebugHelper::assert_((positionAIndex >= 0) && (positionAIndex < vertices.size()),
|
||||
"(ObjBuildModel::ObjBuildModel) Face ", faceIndex, " first index is out of range!");
|
||||
DebugHelper::assert_((positionBIndex >= 0) && (positionBIndex < vertices.size()),
|
||||
"(ObjBuildModel::ObjBuildModel) Face ", faceIndex, " second index is out of range!");
|
||||
DebugHelper::assert_((positionCIndex >= 0) && (positionCIndex < vertices.size()),
|
||||
"(ObjBuildModel::ObjBuildModel) Face ", faceIndex, " third index is out of range!");
|
||||
|
||||
if(faceComponentsA.size() == 1 || faceComponentsA[1].empty()) {
|
||||
DebugHelper::info("No UVs!");
|
||||
// Add the new triangle with no UV coordinates.
|
||||
_add_new_triangle_to_current_block(vertices[positionAIndex], vertices[positionBIndex], vertices[positionCIndex]);
|
||||
} else {
|
||||
int uvAIndex = std::stoi(faceComponentsA[1]) - 1;
|
||||
int uvBIndex = std::stoi(faceComponentsB[1]) - 1;
|
||||
int uvCIndex = std::stoi(faceComponentsC[1]) - 1;
|
||||
|
||||
// Adjust the uv coordinates to the N64 format.
|
||||
Vec2f uv0 = _get_adjusted_uv(uvs[uvAIndex], currentMaterial);
|
||||
Vec2f uv1 = _get_adjusted_uv(uvs[uvBIndex], currentMaterial);
|
||||
Vec2f uv2 = _get_adjusted_uv(uvs[uvCIndex], currentMaterial);
|
||||
|
||||
// Add the new triangle with UV coordinates.
|
||||
_add_new_triangle_to_current_block(vertices[positionAIndex], vertices[positionBIndex], vertices[positionCIndex], uv0, uv1, uv2);
|
||||
for(ObjTriangle &tri : tris) {
|
||||
BuildModelVertex &vertexA = vertices[tri.a.vertexIndex];
|
||||
BuildModelVertex &vertexB = vertices[tri.b.vertexIndex];
|
||||
BuildModelVertex &vertexC = vertices[tri.c.vertexIndex];
|
||||
if(currentMaterial.empty() || (tri.a.uvIndex == -1)) {
|
||||
// Add triangle without UV coordinates.
|
||||
_add_new_triangle_to_current_block(vertexA, vertexB, vertexC);
|
||||
} else {
|
||||
Vec2f uv0 = _get_adjusted_uv(uvs[tri.a.uvIndex], currentMaterial);
|
||||
Vec2f uv1 = _get_adjusted_uv(uvs[tri.b.uvIndex], currentMaterial);
|
||||
Vec2f uv2 = _get_adjusted_uv(uvs[tri.c.uvIndex], currentMaterial);
|
||||
|
||||
// Add the new triangle with UV coordinates.
|
||||
_add_new_triangle_to_current_block(vertexA, vertexB, vertexC, uv0, uv1, uv2);
|
||||
}
|
||||
}
|
||||
|
||||
faceIndex++;
|
||||
continue;
|
||||
}
|
||||
if(components[0] == "usemtl") {
|
||||
@@ -113,8 +169,6 @@ ObjBuildModel::ObjBuildModel(fs::path filepath) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
DebugHelper::info("Done!");
|
||||
}
|
||||
|
||||
Vec2f ObjBuildModel::_get_adjusted_uv(Vec2f uv, std::string materialId) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <cmath> // for std::round
|
||||
|
||||
#include "helpers/assetsHelper.h"
|
||||
#include "helpers/dataHelper.h"
|
||||
#include "helpers/imageHelper.h"
|
||||
#include "helpers/gzipHelper.h"
|
||||
@@ -32,7 +33,9 @@ size_t calculate_out_size(BuildInfo &info, const JsonFile &jsonFile) {
|
||||
}
|
||||
|
||||
void BuildTexture::build(BuildInfo &info) {
|
||||
BuildTextureCache &textureCache = info.get_texture_cache();
|
||||
const JsonFile &jsonFile = info.get_src_json_file();
|
||||
bool is3dTexture = info.get_section_build_id() == "ASSET_TEXTURES_3D";
|
||||
|
||||
info.out.resize(calculate_out_size(info, jsonFile));
|
||||
|
||||
@@ -124,6 +127,12 @@ void BuildTexture::build(BuildInfo &info) {
|
||||
}
|
||||
}
|
||||
|
||||
if(is3dTexture) {
|
||||
// Calculate sha1 of texture data, then add it to the texture cache. Need this so that we can reuse existing textures.
|
||||
std::string textureSha1 = DataHelper::make_sha1_hash_of_bytes(BytesView(info.out));
|
||||
textureCache.add_texture_to_sha1_cache(textureSha1, info.get_build_id());
|
||||
}
|
||||
|
||||
bool debugKeepUncompressed = GlobalSettings::get_value<bool>("/debug/keep-uncompressed", false);
|
||||
|
||||
if(debugKeepUncompressed) {
|
||||
@@ -154,44 +163,105 @@ void BuildTexture::build(BuildInfo &info) {
|
||||
}
|
||||
|
||||
size_t BuildTexture::build_deferred(BuildInfo &baseInfo, fs::path pathToImage) {
|
||||
std::string format = "RGBA16";
|
||||
std::string renderMode = "OPAQUE";
|
||||
std::string format, renderMode;
|
||||
ImageHelper::guess_texture_format_and_render_mode(pathToImage, format, renderMode);
|
||||
|
||||
N64Image img(pathToImage, format);
|
||||
std::vector<fs::path> texturePaths = ImageHelper::get_multiple_textures_from_one(pathToImage);
|
||||
|
||||
int imgWidth = img.get_width();
|
||||
int imgHeight = img.get_height();
|
||||
DebugHelper::assert_(texturePaths.size() > 0,
|
||||
"(BuildTexture::build_deferred) ImageHelper::get_multiple_textures_from_one() failed for ", pathToImage.filename());
|
||||
|
||||
std::vector<uint8_t> out(sizeof(TextureHeader) + ImageHelper::image_size(imgWidth, imgHeight, format));
|
||||
size_t totalSize = 0;
|
||||
|
||||
TextureHeader *header = reinterpret_cast<TextureHeader *>(&out[0]);
|
||||
uint8_t *textureData = &out[sizeof(TextureHeader)];
|
||||
for(auto &path : texturePaths) {
|
||||
int width, height;
|
||||
ImageHelper::get_width_and_height(path, width, height);
|
||||
totalSize += DataHelper::align16(sizeof(TextureHeader) + ImageHelper::image_size(width, height, format));
|
||||
}
|
||||
|
||||
uint8_t formatVal = DataHelper::vector_index_of<std::string>(TEXTURE_FORMAT_INT_TO_STRING, format);
|
||||
uint8_t renderModeVal = DataHelper::vector_index_of<std::string>(TEXTURE_RENDER_MODES, renderMode);
|
||||
DebugHelper::assert_(totalSize > 0,
|
||||
"(BuildTexture::build_deferred) Could not calculate texture size for ", pathToImage.filename());
|
||||
|
||||
header->width = imgWidth;
|
||||
header->height = imgHeight;
|
||||
header->format = (renderModeVal << 4) | formatVal;
|
||||
header->numberOfInstances = 1;
|
||||
header->numOfTextures = 1;
|
||||
header->textureSize = DataHelper::align16(out.size());
|
||||
int frameAdvanceDelay = 0;
|
||||
|
||||
be_int16_t flags = (
|
||||
((int)1 << 10) |
|
||||
((int)1 << 6) |
|
||||
((int)1 << 7)
|
||||
);
|
||||
if(texturePaths.size() > 1) {
|
||||
float animTexTiming = ImageHelper::guess_animated_texture_timing(pathToImage);
|
||||
frameAdvanceDelay = std::round(animTexTiming * TEXTURE_FPS);
|
||||
}
|
||||
|
||||
header->flags = flags;
|
||||
std::string wrapS, wrapT;
|
||||
ImageHelper::guess_texture_wrap_mode(pathToImage, wrapS, wrapT);
|
||||
bool wrapSClamped = wrapS == "clamp";
|
||||
bool wrapTClamped = wrapT == "clamp";
|
||||
|
||||
img.flip_vertically();
|
||||
img.interlace();
|
||||
img.copy_to(textureData);
|
||||
std::vector<uint8_t> out(totalSize);
|
||||
|
||||
size_t offset = 0;
|
||||
for(auto &path : texturePaths) {
|
||||
N64Image img(path, format);
|
||||
|
||||
int imgWidth = img.get_width();
|
||||
int imgHeight = img.get_height();
|
||||
|
||||
TextureHeader *header = reinterpret_cast<TextureHeader *>(&out[offset]);
|
||||
offset += sizeof(TextureHeader);
|
||||
uint8_t *textureData = &out[offset];
|
||||
|
||||
uint8_t formatVal = DataHelper::vector_index_of<std::string>(TEXTURE_FORMAT_INT_TO_STRING, format);
|
||||
uint8_t renderModeVal = DataHelper::vector_index_of<std::string>(TEXTURE_RENDER_MODES, renderMode);
|
||||
|
||||
header->width = imgWidth;
|
||||
header->height = imgHeight;
|
||||
header->format = (renderModeVal << 4) | formatVal;
|
||||
header->numberOfInstances = 1;
|
||||
header->numOfTextures = texturePaths.size();
|
||||
header->textureSize = DataHelper::align16(img.size() + sizeof(TextureHeader));
|
||||
|
||||
if(header->numOfTextures > 1) {
|
||||
header->frameAdvanceDelay = frameAdvanceDelay;
|
||||
}
|
||||
|
||||
int16_t flags = 0;
|
||||
|
||||
if(wrapSClamped) {
|
||||
flags |= (1 << 6);
|
||||
}
|
||||
|
||||
if(wrapTClamped) {
|
||||
flags |= (1 << 7);
|
||||
}
|
||||
|
||||
img.flip_vertically();
|
||||
|
||||
if(!DataHelper::is_power_of_two(imgWidth)) {
|
||||
flags |= (1 << 10);
|
||||
img.interlace();
|
||||
}
|
||||
|
||||
header->flags = flags;
|
||||
|
||||
img.copy_to(textureData);
|
||||
offset += img.size();
|
||||
}
|
||||
|
||||
|
||||
// Need to check the texture cache to see if the texture already exists or not.
|
||||
// Avoiding duplicate textures saves a lot of space in the ROM file.
|
||||
BuildTextureCache &textureCache = baseInfo.get_texture_cache();
|
||||
std::string textureSha1 = DataHelper::make_sha1_hash_of_bytes(BytesView(out));
|
||||
std::optional<std::string> foundTexBuildId = textureCache.get_build_id_of_texture_hash(textureSha1);
|
||||
if(foundTexBuildId.has_value()) {
|
||||
DebugHelper::info_verbose("Found existing texture for ", pathToImage.filename(), ". Will use ID \"", foundTexBuildId.value(), "\".");
|
||||
return AssetsHelper::get_asset_index("ASSET_TEXTURES_3D", foundTexBuildId.value());
|
||||
}
|
||||
|
||||
// Add the new texture to the cache.
|
||||
std::string buildId = baseInfo.get_build_id() + "_" + pathToImage.stem().generic_string();
|
||||
DebugHelper::info_verbose("Created new texture: ", pathToImage.filename(), ", ID: ", buildId);
|
||||
textureCache.add_texture_to_sha1_cache(textureSha1, buildId);
|
||||
|
||||
BuildInfoCollection &collection = baseInfo.get_collection();
|
||||
|
||||
std::string buildId = baseInfo.get_build_id() + "_" + pathToImage.stem().generic_string();
|
||||
StringHelper::make_uppercase(buildId);
|
||||
|
||||
bool debugKeepUncompressed = GlobalSettings::get_value<bool>("/debug/keep-uncompressed", false);
|
||||
|
||||
@@ -25,8 +25,9 @@
|
||||
|
||||
#include "builder/buildInfo.h"
|
||||
#include "builder/buildInfoCollection.h"
|
||||
#include "builder/buildInfoContext.h"
|
||||
#include "builder/buildAssetTable.h"
|
||||
#include "builder/stats.h"
|
||||
#include "builder/textureCache.h"
|
||||
|
||||
#include "buildTypes/buildAudio.h"
|
||||
#include "buildTypes/buildBinary.h"
|
||||
@@ -204,11 +205,11 @@ void AssetBuilder::build_all(const fs::path &dstPath) {
|
||||
size_t numberOfAssetSections = sectionIds.size();
|
||||
|
||||
CContext cContext;
|
||||
BuildStats stats;
|
||||
BuildTextureCache textureCache;
|
||||
BuildInfoCollection collection;
|
||||
|
||||
// BuildInfoContext holds info that is shared between all assets.
|
||||
BuildInfoContext infoContext(cContext, stats, collection);
|
||||
BuildInfoContext infoContext(cContext, textureCache, collection);
|
||||
|
||||
fs::path includeFolder = GlobalSettings::get_decomp_path("include_subpath", "include/");
|
||||
CEnumsHelper::load_enums_from_file(cContext, includeFolder / "enums.h");
|
||||
@@ -254,7 +255,7 @@ void AssetBuilder::build_all(const fs::path &dstPath) {
|
||||
collection.run_builds([](BuildInfo &info) {
|
||||
std::string type = info.get_type();
|
||||
builderMap[type](info);
|
||||
});
|
||||
}, sectionIds);
|
||||
|
||||
// Second loop to create the tables for the asset sections.
|
||||
for(size_t sectionIndex = 0; sectionIndex < numberOfAssetSections; sectionIndex++) {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#include "stats.h"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user