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 struct BSPSurface
{ {
BSPMaterial material; size_t materialIndex;
uint16_t vertexCount; uint16_t vertexCount;
uint16_t triCount; uint16_t triCount;
int indexOfFirstVertex; int indexOfFirstVertex;
@@ -48,6 +48,7 @@ namespace BSP
std::vector<BSPSurface> surfaces; std::vector<BSPSurface> surfaces;
std::vector<BSPVertex> vertices; std::vector<BSPVertex> vertices;
std::vector<uint16_t> indices; std::vector<uint16_t> indices;
std::vector<BSPMaterial> materials;
}; };
struct BSPData struct BSPData
+37 -17
View File
@@ -83,6 +83,7 @@ namespace
private: private:
const Input& m_input; const Input& m_input;
BSPData* m_bsp; BSPData* m_bsp;
size_t m_color_mat_idx;
std::vector<std::unique_ptr<Accessor>> m_accessors; std::vector<std::unique_ptr<Accessor>> m_accessors;
std::vector<std::unique_ptr<BufferView>> m_buffer_views; std::vector<std::unique_ptr<BufferView>> m_buffer_views;
std::vector<std::unique_ptr<Buffer>> m_buffers; std::vector<std::unique_ptr<Buffer>> m_buffers;
@@ -316,27 +317,15 @@ namespace
void loadSurfaceMaterialData(const JsonRoot& jRoot, const JsonMeshPrimitives& primitive, BSPSurface& surface) void loadSurfaceMaterialData(const JsonRoot& jRoot, const JsonMeshPrimitives& primitive, BSPSurface& surface)
{ {
BSPMaterialType matType;
if (!primitive.material) 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()) if (!primitive.attributes.COLOR_0)
throw GltfLoadException("Invalid material index"); throw GltfLoadException("Primitive requires material or colour data.");
surface.material.materialName = jRoot.materials.value()[primitive.material.value()].name.value();
surface.materialIndex = m_color_mat_idx;
} }
else else
surface.material.materialName = ""; surface.materialIndex = *primitive.material;
} }
bool CreateSurfacesFromNode(const JsonRoot& jRoot, const gltf::JsonNode& node) bool CreateSurfacesFromNode(const JsonRoot& jRoot, const gltf::JsonNode& node)
@@ -414,6 +403,36 @@ namespace
return rootNodes; 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) void TraverseNodes(const JsonRoot& jRoot)
{ {
// Make sure there are any nodes to traverse // Make sure there are any nodes to traverse
@@ -551,6 +570,7 @@ namespace
CreateBufferViews(jRoot); CreateBufferViews(jRoot);
CreateAccessors(jRoot); CreateAccessors(jRoot);
LoadMaterials(jRoot);
TraverseNodes(jRoot); TraverseNodes(jRoot);
} }
catch (const GltfLoadException& e) catch (const GltfLoadException& e)
@@ -220,6 +220,8 @@ namespace BSP
if (remainder > 0) if (remainder > 0)
parentCount++; parentCount++;
// the material index of the AABB tree is only checked for the parent node, so
size_t parentAABBArrayIndex = AABBTreeVec.size(); size_t parentAABBArrayIndex = AABBTreeVec.size();
AABBTreeVec.resize(AABBTreeVec.size() + parentCount); AABBTreeVec.resize(AABBTreeVec.size() + parentCount);
size_t unaddedObjectCount = leafObjectCount; size_t unaddedObjectCount = leafObjectCount;
@@ -232,7 +234,7 @@ namespace BSP
else else
unaddedObjectCount -= BSPGameConstants::MAX_AABB_TREE_CHILDREN; unaddedObjectCount -= BSPGameConstants::MAX_AABB_TREE_CHILDREN;
// add the parent AABB // calculate parent AABB mins and maxs
vec3_t parentMins; vec3_t parentMins;
vec3_t parentMaxs; vec3_t parentMaxs;
for (size_t objectIdx = 0; objectIdx < childObjectCount; objectIdx++) for (size_t objectIdx = 0; objectIdx < childObjectCount; objectIdx++)
@@ -259,7 +261,7 @@ namespace BSP
CollisionAabbTree parentAABB; CollisionAabbTree parentAABB;
parentAABB.origin = BSPUtil::calcMiddleOfAABB(parentMins, parentMaxs); parentAABB.origin = BSPUtil::calcMiddleOfAABB(parentMins, parentMaxs);
parentAABB.halfSize = BSPUtil::calcHalfSizeOfAABB(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.childCount = static_cast<uint16_t>(childObjectCount);
parentAABB.u.firstChildIndex = static_cast<int>(childObjectStartIndex); parentAABB.u.firstChildIndex = static_cast<int>(childObjectStartIndex);
AABBTreeVec.at(parentAABBArrayIndex + parentIdx) = parentAABB; 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. // 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<CollisionPartition> partitionVec;
std::vector<uint16_t> uniqueIndicesVec; 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. // 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). // 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 // 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]); uniqueIndicesVec.emplace_back(tri[2]);
partitionVec.emplace_back(partition); partitionVec.emplace_back(partition);
partitionToSurfaceMap.emplace_back(surfIdx);
} }
} }
clipMap->partitionCount = static_cast<int>(partitionVec.size()); clipMap->partitionCount = static_cast<int>(partitionVec.size());
@@ -607,6 +613,29 @@ namespace BSP
return true; 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* ClipMapLinker::linkClipMap(BSPData* bsp)
{ {
clipMap_t* clipMap = m_memory.Alloc<clipMap_t>(); clipMap_t* clipMap = m_memory.Alloc<clipMap_t>();
@@ -631,13 +660,7 @@ namespace BSP
loadXModelCollision(clipMap); loadXModelCollision(clipMap);
// Clipmap materials define the properties of a material (bullet penetration, no collision, water, etc) loadMaterials(clipMap, bsp);
// 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;
if (!loadWorldCollision(clipMap, bsp)) if (!loadWorldCollision(clipMap, bsp))
return nullptr; return nullptr;
@@ -31,10 +31,13 @@ namespace BSP
std::vector<cLeaf_s> leafVec; std::vector<cLeaf_s> leafVec;
std::vector<CollisionAabbTree> AABBTreeVec; std::vector<CollisionAabbTree> AABBTreeVec;
size_t highestLeafObjectCount = 0; 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); void addAABBTreeFromLeaf(clipMap_t* clipMap, BSPTree* tree, size_t* out_parentCount, size_t* out_parentStartIndex);
int16_t loadBSPNode(clipMap_t* clipMap, BSPTree* tree); int16_t loadBSPNode(clipMap_t* clipMap, BSPTree* tree);
bool loadBSPTree(clipMap_t* clipMap, BSPData* bsp); bool loadBSPTree(clipMap_t* clipMap, BSPData* bsp);
bool loadPartitions(clipMap_t* clipMap, BSPData* bsp); bool loadPartitions(clipMap_t* clipMap, BSPData* bsp);
bool loadWorldCollision(clipMap_t* clipMap, BSPData* bsp); bool loadWorldCollision(clipMap_t* clipMap, BSPData* bsp);
bool loadMaterials(clipMap_t* clipMap, BSPData* bsp);
}; };
} // namespace BSP } // namespace BSP
@@ -73,22 +73,21 @@ namespace BSP
gfxSurface->tris.vertexDataOffset0 = bspSurface.indexOfFirstVertex * sizeof(GfxPackedWorldVertex); gfxSurface->tris.vertexDataOffset0 = bspSurface.indexOfFirstVertex * sizeof(GfxPackedWorldVertex);
gfxSurface->tris.vertexDataOffset1 = 0; // vd1 is unused gfxSurface->tris.vertexDataOffset1 = 0; // vd1 is unused
std::string surfMaterialName; BSPMaterial bspMaterial = bsp->colWorld.materials.at(bspSurface.materialIndex);
if (bspSurface.material.materialType == MATERIAL_TYPE_TEXTURE)
surfMaterialName = bspSurface.material.materialName;
else // MATERIAL_TYPE_COLOUR || MATERIAL_TYPE_EMPTY
surfMaterialName = BSPLinkingConstants::COLOR_ONLY_IMAGE_NAME;
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) if (surfMaterialAsset == nullptr)
{ {
std::string missingImageName = BSPLinkingConstants::MISSING_IMAGE_NAME; surfMaterialAsset = m_context.LoadDependency<AssetMaterial>(BSPLinkingConstants::MISSING_IMAGE_NAME);
surfMaterialAsset = m_context.LoadDependency<AssetMaterial>(missingImageName); assert(surfMaterialAsset != nullptr);
if (surfMaterialAsset == nullptr)
{
con::error("unable to load the missing image texture {}!", missingImageName);
return false;
}
} }
gfxSurface->material = surfMaterialAsset->Asset(); gfxSurface->material = surfMaterialAsset->Asset();