2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-06-06 08:42:35 +00:00

Materials now have their own vector and are acessed via indexes

This commit is contained in:
LJW-Dev
2026-02-10 21:35:16 +08:00
committed by Jan Laupetin
parent b5499b7a19
commit a3953e2217
5 changed files with 87 additions and 41 deletions
+2 -1
View File
@@ -36,7 +36,7 @@ namespace BSP
struct BSPSurface
{
BSPMaterial material;
size_t materialIndex;
uint16_t vertexCount;
uint16_t triCount;
int indexOfFirstVertex;
@@ -48,6 +48,7 @@ namespace BSP
std::vector<BSPSurface> surfaces;
std::vector<BSPVertex> vertices;
std::vector<uint16_t> indices;
std::vector<BSPMaterial> materials;
};
struct BSPData
+35 -15
View File
@@ -83,6 +83,7 @@ namespace
private:
const Input& m_input;
BSPData* m_bsp;
size_t m_color_mat_idx;
std::vector<std::unique_ptr<Accessor>> m_accessors;
std::vector<std::unique_ptr<BufferView>> m_buffer_views;
std::vector<std::unique_ptr<Buffer>> m_buffers;
@@ -316,27 +317,15 @@ namespace
void loadSurfaceMaterialData(const JsonRoot& jRoot, const JsonMeshPrimitives& primitive, BSPSurface& surface)
{
BSPMaterialType matType;
if (!primitive.material)
{
if (!primitive.attributes.COLOR_0)
{
// matType = MATERIAL_TYPE_EMPTY;
throw GltfLoadException("Primitive requires material or colour data.");
}
else
matType = MATERIAL_TYPE_COLOUR;
else
matType = MATERIAL_TYPE_TEXTURE;
surface.material.materialType = matType;
if (matType == MATERIAL_TYPE_TEXTURE)
{
if (!jRoot.materials || *primitive.material >= jRoot.materials->size())
throw GltfLoadException("Invalid material index");
surface.material.materialName = jRoot.materials.value()[primitive.material.value()].name.value();
surface.materialIndex = m_color_mat_idx;
}
else
surface.material.materialName = "";
surface.materialIndex = *primitive.material;
}
bool CreateSurfacesFromNode(const JsonRoot& jRoot, const gltf::JsonNode& node)
@@ -414,6 +403,36 @@ namespace
return rootNodes;
}
void LoadMaterials(const JsonRoot& jRoot)
{
if (!jRoot.materials)
return;
m_bsp->gfxWorld.materials.reserve((*jRoot.materials).size());
for (auto& jsMaterial : *jRoot.materials)
{
BSPMaterial material;
if (jsMaterial.name && (*jsMaterial.name).length() != 0)
{
material.materialType = MATERIAL_TYPE_TEXTURE;
material.materialName = *jsMaterial.name;
}
else
{
material.materialType = MATERIAL_TYPE_EMPTY;
material.materialName = "";
}
m_bsp->gfxWorld.materials.emplace_back(material);
}
m_color_mat_idx = m_bsp->gfxWorld.materials.size();
BSPMaterial colorMaterial;
colorMaterial.materialType = MATERIAL_TYPE_COLOUR;
colorMaterial.materialName = "";
m_bsp->gfxWorld.materials.emplace_back(colorMaterial);
}
void TraverseNodes(const JsonRoot& jRoot)
{
// Make sure there are any nodes to traverse
@@ -551,6 +570,7 @@ namespace
CreateBufferViews(jRoot);
CreateAccessors(jRoot);
LoadMaterials(jRoot);
TraverseNodes(jRoot);
}
catch (const GltfLoadException& e)
@@ -220,6 +220,8 @@ namespace BSP
if (remainder > 0)
parentCount++;
// the material index of the AABB tree is only checked for the parent node, so
size_t parentAABBArrayIndex = AABBTreeVec.size();
AABBTreeVec.resize(AABBTreeVec.size() + parentCount);
size_t unaddedObjectCount = leafObjectCount;
@@ -232,7 +234,7 @@ namespace BSP
else
unaddedObjectCount -= BSPGameConstants::MAX_AABB_TREE_CHILDREN;
// add the parent AABB
// calculate parent AABB mins and maxs
vec3_t parentMins;
vec3_t parentMaxs;
for (size_t objectIdx = 0; objectIdx < childObjectCount; objectIdx++)
@@ -259,7 +261,7 @@ namespace BSP
CollisionAabbTree parentAABB;
parentAABB.origin = BSPUtil::calcMiddleOfAABB(parentMins, parentMaxs);
parentAABB.halfSize = BSPUtil::calcHalfSizeOfAABB(parentMins, parentMaxs);
parentAABB.materialIndex = 0; // always use the first material
parentAABB.materialIndex = 0;
parentAABB.childCount = static_cast<uint16_t>(childObjectCount);
parentAABB.u.firstChildIndex = static_cast<int>(childObjectStartIndex);
AABBTreeVec.at(parentAABBArrayIndex + parentIdx) = parentAABB;
@@ -505,8 +507,10 @@ namespace BSP
// partitions are "containers" for vertices. BSP tree leafs contain a list of these partitions to determine the collision within a leaf.
std::vector<CollisionPartition> partitionVec;
std::vector<uint16_t> uniqueIndicesVec;
for (BSPSurface& surface : bsp->colWorld.surfaces)
for (size_t surfIdx = 0; surfIdx < bsp->colWorld.surfaces.size(); surfIdx++)
{
BSPSurface& surface = bsp->colWorld.surfaces[surfIdx];
// partitions are made for each triangle, not one for each surface.
// one for each surface causes physics bugs, as the entire bounding box is considered solid instead of the surface itself (for some reason).
// so a partition is made for each triangle which removes the physics bugs but likely makes the game run slower
@@ -528,6 +532,8 @@ namespace BSP
uniqueIndicesVec.emplace_back(tri[2]);
partitionVec.emplace_back(partition);
partitionToSurfaceMap.emplace_back(surfIdx);
}
}
clipMap->partitionCount = static_cast<int>(partitionVec.size());
@@ -607,6 +613,29 @@ namespace BSP
return true;
}
bool ClipMapLinker::loadMaterials(clipMap_t* clipMap, BSPData* bsp)
{
// Clipmap materials define the properties of a material (bullet penetration, no collision, water, etc)
if (bsp->colWorld.materials.size() > UINT16_MAX)
{
con::error("Collision map exceeds 0xFFFF materials");
return false;
}
clipMap->info.numMaterials = static_cast<unsigned int>(bsp->colWorld.materials.size());
clipMap->info.materials = m_memory.Alloc<ClipMaterial>(clipMap->info.numMaterials);
for (size_t matIdx = 0; matIdx < bsp->colWorld.materials.size(); matIdx++)
{
ClipMaterial* clipMat = &clipMap->info.materials[matIdx];
BSPMaterial bspMat = bsp->colWorld.materials.at(matIdx);
clipMat->name = m_memory.Dup(bspMat.materialName.c_str());
clipMat->contentFlags = BSPEditableConstants::MATERIAL_CONTENT_FLAGS;
clipMat->surfaceFlags = BSPEditableConstants::MATERIAL_SURFACE_FLAGS;
}
}
clipMap_t* ClipMapLinker::linkClipMap(BSPData* bsp)
{
clipMap_t* clipMap = m_memory.Alloc<clipMap_t>();
@@ -631,13 +660,7 @@ namespace BSP
loadXModelCollision(clipMap);
// Clipmap materials define the properties of a material (bullet penetration, no collision, water, etc)
// Right now there is no way to define properties per material so only one material is used
clipMap->info.numMaterials = 1;
clipMap->info.materials = m_memory.Alloc<ClipMaterial>(clipMap->info.numMaterials);
clipMap->info.materials[0].name = m_memory.Dup(BSPLinkingConstants::MISSING_IMAGE_NAME);
clipMap->info.materials[0].contentFlags = BSPEditableConstants::MATERIAL_CONTENT_FLAGS;
clipMap->info.materials[0].surfaceFlags = BSPEditableConstants::MATERIAL_SURFACE_FLAGS;
loadMaterials(clipMap, bsp);
if (!loadWorldCollision(clipMap, bsp))
return nullptr;
@@ -31,10 +31,13 @@ namespace BSP
std::vector<cLeaf_s> leafVec;
std::vector<CollisionAabbTree> AABBTreeVec;
size_t highestLeafObjectCount = 0;
std::vector<unsigned> partitionToSurfaceMap;
std::vector<unsigned> surfaceToMaterialMap;
void addAABBTreeFromLeaf(clipMap_t* clipMap, BSPTree* tree, size_t* out_parentCount, size_t* out_parentStartIndex);
int16_t loadBSPNode(clipMap_t* clipMap, BSPTree* tree);
bool loadBSPTree(clipMap_t* clipMap, BSPData* bsp);
bool loadPartitions(clipMap_t* clipMap, BSPData* bsp);
bool loadWorldCollision(clipMap_t* clipMap, BSPData* bsp);
bool loadMaterials(clipMap_t* clipMap, BSPData* bsp);
};
} // namespace BSP
@@ -73,22 +73,21 @@ namespace BSP
gfxSurface->tris.vertexDataOffset0 = bspSurface.indexOfFirstVertex * sizeof(GfxPackedWorldVertex);
gfxSurface->tris.vertexDataOffset1 = 0; // vd1 is unused
std::string surfMaterialName;
if (bspSurface.material.materialType == MATERIAL_TYPE_TEXTURE)
surfMaterialName = bspSurface.material.materialName;
else // MATERIAL_TYPE_COLOUR || MATERIAL_TYPE_EMPTY
surfMaterialName = BSPLinkingConstants::COLOR_ONLY_IMAGE_NAME;
BSPMaterial bspMaterial = bsp->colWorld.materials.at(bspSurface.materialIndex);
auto surfMaterialAsset = m_context.LoadDependency<AssetMaterial>(surfMaterialName);
std::string materialName;
if (bspMaterial.materialType == MATERIAL_TYPE_EMPTY)
materialName = BSPLinkingConstants::MISSING_IMAGE_NAME;
else if (bspMaterial.materialType == MATERIAL_TYPE_COLOUR)
materialName = BSPLinkingConstants::COLOR_ONLY_IMAGE_NAME;
else // MATERIAL_TYPE_TEXTURE
materialName = bspMaterial.materialName;
auto surfMaterialAsset = m_context.LoadDependency<AssetMaterial>(materialName);
if (surfMaterialAsset == nullptr)
{
std::string missingImageName = BSPLinkingConstants::MISSING_IMAGE_NAME;
surfMaterialAsset = m_context.LoadDependency<AssetMaterial>(missingImageName);
if (surfMaterialAsset == nullptr)
{
con::error("unable to load the missing image texture {}!", missingImageName);
return false;
}
surfMaterialAsset = m_context.LoadDependency<AssetMaterial>(BSPLinkingConstants::MISSING_IMAGE_NAME);
assert(surfMaterialAsset != nullptr);
}
gfxSurface->material = surfMaterialAsset->Asset();