diff --git a/src/ObjCommon/Material/MaterialCommon.cpp b/src/ObjCommon/Material/MaterialCommon.cpp new file mode 100644 index 00000000..f9bc1251 --- /dev/null +++ b/src/ObjCommon/Material/MaterialCommon.cpp @@ -0,0 +1,35 @@ +#include "MaterialCommon.h" + +using namespace material; + +CommonConstant::CommonConstant() + : m_literal{} +{ +} + +CommonMaterial::CommonMaterial() + : m_game_flags(0u), + m_sort_key(0u), + m_texture_atlas_row_count(0u), + m_texture_atlas_column_count(0u), + m_surface_flags(0u), + m_contents(0u), + m_ref_state_bits{} +{ +} + +CommonTexture::CommonTexture() + : m_sampler_state(0u), + m_semantic(0u) +{ +} + +CommonWaterDef::CommonWaterDef() + : m_texture_width(0u), + m_horizontal_world_length(0u), + m_vertical_world_length(0u), + m_amplitude(0u), + m_wind_speed(0u), + m_wind_direction{} +{ +} diff --git a/src/ObjCommon/Material/MaterialCommon.h b/src/ObjCommon/Material/MaterialCommon.h new file mode 100644 index 00000000..173ce0f3 --- /dev/null +++ b/src/ObjCommon/Material/MaterialCommon.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include +#include + +namespace material +{ + class CommonWaterDef + { + public: + int m_texture_width; + float m_horizontal_world_length; + float m_vertical_world_length; + float m_amplitude; + float m_wind_speed; + float m_wind_direction[2]; + + CommonWaterDef(); + }; + + class CommonTexture + { + public: + std::string m_name; + uint8_t m_sampler_state; + uint8_t m_semantic; + std::string m_image_name; + std::unique_ptr m_water_def; + + CommonTexture(); + }; + + class CommonConstant + { + public: + std::string m_name; + float m_literal[4]; + + CommonConstant(); + }; + + class CommonMaterial + { + public: + std::string m_name; + uint8_t m_game_flags; + uint8_t m_sort_key; + uint8_t m_texture_atlas_row_count; + uint8_t m_texture_atlas_column_count; + uint32_t m_surface_flags; + uint32_t m_contents; + uint32_t m_ref_state_bits[2]; + std::vector m_textures; + std::vector m_constants; + std::string m_techset_name; + + CommonMaterial(); + }; +} diff --git a/src/ObjCommon/Material/Raw/MaterialRawOat.h b/src/ObjCommon/Material/Raw/MaterialRawOat.h new file mode 100644 index 00000000..940c9d83 --- /dev/null +++ b/src/ObjCommon/Material/Raw/MaterialRawOat.h @@ -0,0 +1,59 @@ +#pragma once + +#include + +namespace material +{ + struct MaterialRawOatHeader + { + uint8_t magic[3]; + uint8_t version; + }; + + struct MaterialInfoRaw + { + uint32_t nameOffset; + uint8_t gameFlags; + uint8_t sortKey; + uint8_t textureAtlasRowCount; + uint8_t textureAtlasColumnCount; + uint32_t surfaceFlags; + uint32_t contents; + }; + + struct MaterialRaw + { + MaterialInfoRaw info; + uint32_t refStateBits[2]; + uint16_t textureCount; + uint16_t constantCount; + uint32_t techSetNameOffset; + uint32_t textureTableOffset; + uint32_t constantTableOffset; + }; + + struct MaterialTextureDefRaw + { + uint32_t nameOffset; + uint8_t samplerState; + uint8_t semantic; + uint32_t imageNameOffset; + uint32_t waterDefOffset; + }; + + struct MaterialWaterDefRaw + { + uint32_t textureWidth; + float horizontalWorldLength; + float verticalWorldLength; + float amplitude; + float windSpeed; + float windDirection[2]; + }; + + struct MaterialConstantDefRaw + { + uint32_t nameOffset; + float literal[4]; + }; +} \ No newline at end of file diff --git a/src/ObjWriting/Dumping/AbstractRawDumper.cpp b/src/ObjWriting/Dumping/AbstractRawDumper.cpp new file mode 100644 index 00000000..52da9abc --- /dev/null +++ b/src/ObjWriting/Dumping/AbstractRawDumper.cpp @@ -0,0 +1,30 @@ +#include "AbstractRawDumper.h" + +AbstractRawDumper::AbstractRawDumper(std::ostream& stream) + : m_stream(stream), + m_current_offset(0u) +{ +} + +size_t AbstractRawDumper::OffsetAdd(const size_t len) +{ + const auto lastOffset = m_current_offset; + m_current_offset += len; + + return lastOffset; +} + +size_t AbstractRawDumper::OffsetAdd(const std::string& str) +{ + return OffsetAdd(str.size() + 1); +} + +void AbstractRawDumper::Write(const void* ptr, const size_t size) const +{ + m_stream.write(static_cast(ptr), size); +} + +void AbstractRawDumper::Write(const std::string& str) const +{ + m_stream.write(str.c_str(), str.size() + 1); +} diff --git a/src/ObjWriting/Dumping/AbstractRawDumper.h b/src/ObjWriting/Dumping/AbstractRawDumper.h new file mode 100644 index 00000000..61f35616 --- /dev/null +++ b/src/ObjWriting/Dumping/AbstractRawDumper.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class AbstractRawDumper +{ +protected: + explicit AbstractRawDumper(std::ostream& stream); + +public: + virtual ~AbstractRawDumper() = default; + AbstractRawDumper(const AbstractRawDumper& other) = default; + AbstractRawDumper(AbstractRawDumper&& other) noexcept = default; + AbstractRawDumper& operator=(const AbstractRawDumper& other) = delete; + AbstractRawDumper& operator=(AbstractRawDumper&& other) noexcept = delete; + +protected: + size_t OffsetAdd(size_t len); + size_t OffsetAdd(const std::string& str); + void Write(const void* ptr, size_t size) const; + void Write(const std::string& str) const; + + std::ostream& m_stream; + size_t m_current_offset; +}; \ No newline at end of file diff --git a/src/ObjWriting/Material/Raw/MaterialRawOatWriter.cpp b/src/ObjWriting/Material/Raw/MaterialRawOatWriter.cpp new file mode 100644 index 00000000..3e86118a --- /dev/null +++ b/src/ObjWriting/Material/Raw/MaterialRawOatWriter.cpp @@ -0,0 +1,101 @@ +#include "MaterialRawOatWriter.h" + +#include "Material/Raw/MaterialRawOat.h" + +using namespace material; + +MaterialRawOatWriter::MaterialRawOatWriter(std::ostream& stream) + : AbstractRawDumper(stream) +{ +} + +void MaterialRawOatWriter::WriteMaterial(const CommonMaterial& material) +{ + constexpr MaterialRawOatHeader header{ + {'M', 'T', 'L'}, + 1u + }; + OffsetAdd(sizeof(header)); + + MaterialRaw materialRaw{}; + OffsetAdd(sizeof(materialRaw)); + + materialRaw.info.nameOffset = OffsetAdd(material.m_name); + materialRaw.info.gameFlags = material.m_game_flags; + materialRaw.info.sortKey = material.m_sort_key; + materialRaw.info.textureAtlasRowCount = material.m_texture_atlas_row_count; + materialRaw.info.textureAtlasColumnCount = material.m_texture_atlas_column_count; + materialRaw.info.surfaceFlags = material.m_surface_flags; + materialRaw.info.contents = material.m_contents; + materialRaw.refStateBits[0] = material.m_ref_state_bits[0]; + materialRaw.refStateBits[1] = material.m_ref_state_bits[1]; + materialRaw.textureCount = static_cast(material.m_textures.size()); + materialRaw.constantCount = static_cast(material.m_textures.size()); + materialRaw.techSetNameOffset = OffsetAdd(material.m_techset_name); + materialRaw.textureTableOffset = OffsetAdd(sizeof(MaterialTextureDefRaw) * material.m_textures.size()); + materialRaw.constantTableOffset = OffsetAdd(sizeof(MaterialConstantDefRaw) * material.m_textures.size()); + + const auto textureCount = material.m_textures.size(); + std::vector textureDefs(textureCount); + for (auto i = 0u; i < textureCount; i++) + { + const auto& texture = material.m_textures[i]; + auto& textureDef = textureDefs[i]; + + textureDef.nameOffset = OffsetAdd(texture.m_name); + textureDef.samplerState = texture.m_sampler_state; + textureDef.semantic = texture.m_semantic; + textureDef.imageNameOffset = OffsetAdd(texture.m_image_name); + textureDef.waterDefOffset = texture.m_water_def ? OffsetAdd(sizeof(MaterialWaterDefRaw)) : 0u; + } + + const auto constantCount = material.m_constants.size(); + std::vector constantDefs(constantCount); + for (auto i = 0u; i < constantCount; i++) + { + const auto& constant = material.m_constants[i]; + auto& constantDef = constantDefs[i]; + + constantDef.nameOffset = OffsetAdd(constant.m_name); + constantDef.literal[0] = constant.m_literal[0]; + constantDef.literal[1] = constant.m_literal[1]; + constantDef.literal[2] = constant.m_literal[2]; + constantDef.literal[3] = constant.m_literal[3]; + } + + Write(&header, sizeof(header)); + Write(&materialRaw, sizeof(materialRaw)); + Write(material.m_name); + Write(material.m_techset_name); + Write(textureDefs.data(), sizeof(MaterialTextureDefRaw) * textureCount); + Write(constantDefs.data(), sizeof(MaterialConstantDefRaw) * constantCount); + + for (auto i = 0u; i < textureCount; i++) + { + const auto& texture = material.m_textures[i]; + + Write(texture.m_name); + Write(texture.m_image_name); + + if (texture.m_water_def) + { + const auto& water = *texture.m_water_def; + MaterialWaterDefRaw waterDef{}; + waterDef.textureWidth = water.m_texture_width; + waterDef.horizontalWorldLength = water.m_horizontal_world_length; + waterDef.verticalWorldLength = water.m_vertical_world_length; + waterDef.amplitude = water.m_amplitude; + waterDef.windSpeed = water.m_wind_speed; + waterDef.windDirection[0] = water.m_wind_direction[0]; + waterDef.windDirection[1] = water.m_wind_direction[1]; + + Write(&waterDef, sizeof(MaterialWaterDefRaw)); + } + } + + for (auto i = 0u; i < constantCount; i++) + { + const auto& constant = material.m_constants[i]; + Write(constant.m_name); + } +} diff --git a/src/ObjWriting/Material/Raw/MaterialRawOatWriter.h b/src/ObjWriting/Material/Raw/MaterialRawOatWriter.h new file mode 100644 index 00000000..0cf87968 --- /dev/null +++ b/src/ObjWriting/Material/Raw/MaterialRawOatWriter.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "Dumping/AbstractRawDumper.h" +#include "Material/MaterialCommon.h" + +namespace material +{ + class MaterialRawOatWriter final : AbstractRawDumper + { + public: + explicit MaterialRawOatWriter(std::ostream& stream); + + void WriteMaterial(const CommonMaterial& material); + }; +} + \ No newline at end of file