mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-18 16:32:32 +02:00
Added multimaterial support
This commit is contained in:
parent
125f339232
commit
db3fc6f2dd
@ -78,12 +78,15 @@ std::unique_ptr<Model> LoaderDFF::loadFromMemory(char *data)
|
||||
size_t matI = 0;
|
||||
materiallistsec.getNextChildSection(matI);
|
||||
|
||||
geometryStruct.materials.resize(materialList.nummaterials);
|
||||
|
||||
for (size_t m = 0; m < materialList.nummaterials; ++m) {
|
||||
auto materialsec = materiallistsec.getNextChildSection(matI);
|
||||
if (materialsec.header.id != RW::SID_Material)
|
||||
continue;
|
||||
|
||||
auto material = materialsec.readStructure<RW::BSMaterial>();
|
||||
geometryStruct.materials[m].textures.resize(material.numtextures);
|
||||
|
||||
size_t texI = 0;
|
||||
materialsec.getNextChildSection(texI);
|
||||
@ -103,13 +106,44 @@ std::unique_ptr<Model> LoaderDFF::loadFromMemory(char *data)
|
||||
textureName = namesec.raw();
|
||||
alphaName = alphasec.raw();
|
||||
|
||||
geometryStruct.textures.push_back({textureName, alphaName});
|
||||
geometryStruct.materials[m].textures[t] = {textureName, alphaName};
|
||||
}
|
||||
}
|
||||
|
||||
if(item.hasMoreData(secI))
|
||||
{
|
||||
auto extensions = item.getNextChildSection(secI);
|
||||
size_t extI = 0;
|
||||
while(extensions.hasMoreData(extI))
|
||||
{
|
||||
auto extsec = extensions.getNextChildSection(extI);
|
||||
if(extsec.header.id == RW::SID_BinMeshPLG)
|
||||
{
|
||||
auto meshplg = extsec.readSubStructure<RW::BSBinMeshPLG>(0);
|
||||
geometryStruct.subgeom.resize(meshplg.numsplits);
|
||||
size_t meshplgI = sizeof(RW::BSBinMeshPLG);
|
||||
for(size_t i = 0; i < meshplg.numsplits; ++i)
|
||||
{
|
||||
auto plgHeader = extsec.readSubStructure<RW::BSMaterialSplit>(meshplgI);
|
||||
meshplgI += sizeof(RW::BSMaterialSplit);
|
||||
geometryStruct.subgeom[i].material = plgHeader.index;
|
||||
geometryStruct.subgeom[i].indices.resize(plgHeader.numverts);
|
||||
for (int j = 0; j < plgHeader.numverts; ++j) {
|
||||
geometryStruct.subgeom[i].indices[j] = extsec.readSubStructure<uint32_t>(meshplgI);
|
||||
meshplgI += sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OpenGL buffer stuff
|
||||
glGenBuffers(1, &geometryStruct.VBO);
|
||||
glGenBuffers(1, &geometryStruct.EBO);
|
||||
for(size_t i = 0; i < geometryStruct.subgeom.size(); ++i)
|
||||
{
|
||||
glGenBuffers(1, &(geometryStruct.subgeom[i].EBO));
|
||||
}
|
||||
|
||||
size_t buffsize = (geometryStruct.vertices.size() * sizeof(float) * 3)
|
||||
+ (geometryStruct.texcoords.size() * sizeof(float) * 2)
|
||||
@ -163,8 +197,21 @@ std::unique_ptr<Model> LoaderDFF::loadFromMemory(char *data)
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
|
||||
for(size_t i = 0; i < geometryStruct.subgeom.size(); ++i)
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometryStruct.subgeom[i].EBO);
|
||||
glBufferData(
|
||||
GL_ELEMENT_ARRAY_BUFFER,
|
||||
sizeof(uint32_t) * geometryStruct.subgeom[i].indices.size(),
|
||||
&(geometryStruct.subgeom[i].indices[0]),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
}
|
||||
|
||||
// Add it
|
||||
model->geometries.push_back(geometryStruct);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,17 @@ public:
|
||||
std::string name;
|
||||
std::string alphaName;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
std::vector<Texture> textures;
|
||||
};
|
||||
|
||||
struct SubGeometry {
|
||||
GLuint EBO;
|
||||
size_t material;
|
||||
std::vector<uint32_t> indices;
|
||||
};
|
||||
|
||||
struct Geometry {
|
||||
GLuint VBO, EBO;
|
||||
|
||||
@ -28,7 +39,8 @@ public:
|
||||
std::vector<RW::BSTVector3> vertices;
|
||||
std::vector<RW::BSTVector3> normals;
|
||||
|
||||
std::vector<Texture> textures;
|
||||
std::vector<Material> materials;
|
||||
std::vector<SubGeometry> subgeom;
|
||||
};
|
||||
|
||||
std::vector<Geometry> geometries;
|
||||
|
@ -33,6 +33,8 @@ namespace RW
|
||||
|
||||
SID_HAnimPLG = 0x011E,
|
||||
|
||||
SID_BinMeshPLG = 0x50E,
|
||||
|
||||
SID_NodeName = 0x0253F2FE
|
||||
};
|
||||
|
||||
@ -166,6 +168,19 @@ namespace RW
|
||||
uint16_t unknown;
|
||||
};
|
||||
|
||||
struct BSBinMeshPLG
|
||||
{
|
||||
uint32_t facetype;
|
||||
uint32_t numsplits;
|
||||
uint32_t numfaces;
|
||||
};
|
||||
|
||||
struct BSMaterialSplit
|
||||
{
|
||||
uint32_t numverts;
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
/**
|
||||
* Texture Dictionary Structures (TXD)
|
||||
*/
|
||||
@ -284,6 +299,11 @@ namespace RW
|
||||
return *reinterpret_cast<T*>(data+offset+sizeof(BSSectionHeader)+internalOffset);
|
||||
}
|
||||
|
||||
template<class T> T readRaw(size_t internalOffset)
|
||||
{
|
||||
return *reinterpret_cast<T*>(data+offset+internalOffset);
|
||||
}
|
||||
|
||||
char* raw()
|
||||
{
|
||||
return data + offset + sizeof(BSSectionHeader);
|
||||
|
@ -242,11 +242,6 @@ void render()
|
||||
// std::cout << "Rendering " << modelname << std::endl;
|
||||
|
||||
for (size_t g = 0; g < model->geometries.size(); g++) {
|
||||
if (model->geometries[g].textures.size() > 0) {
|
||||
// std::cout << model->geometries[g].textures.size() << std::endl;
|
||||
// std::cout << "Looking for " << model->geometries[g].textures[0].name << std::endl;
|
||||
textureLoader.bindTexture(model->geometries[g].textures[0].name);
|
||||
}
|
||||
|
||||
// This is a hack I have no idea why negating the quaternion fixes the issue but it does.
|
||||
glm::quat rot(-obj.rotW, obj.rotX, obj.rotY, obj.rotZ);
|
||||
@ -257,13 +252,25 @@ void render()
|
||||
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(matrixModel));
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, model->geometries[g].VBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->geometries[g].EBO);
|
||||
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, (void*)(model->geometries[g].vertices.size() * sizeof(float) * 3));
|
||||
glEnableVertexAttribArray(posAttrib);
|
||||
glEnableVertexAttribArray(texAttrib);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, model->geometries[g].triangles.size() * 3, GL_UNSIGNED_SHORT, NULL);
|
||||
for(size_t sg = 0; sg < model->geometries[g].subgeom.size(); ++sg)
|
||||
{
|
||||
if (model->geometries[g].materials.size() > model->geometries[g].subgeom[sg].material) {
|
||||
// std::cout << model->geometries[g].textures.size() << std::endl;
|
||||
// std::cout << "Looking for " << model->geometries[g].textures[0].name << std::endl;
|
||||
if(model->geometries[g].materials[model->geometries[g].subgeom[sg].material].textures.size() > 0) {
|
||||
textureLoader.bindTexture(model->geometries[g].materials[model->geometries[g].subgeom[sg].material].textures[0].name);
|
||||
}
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->geometries[g].subgeom[sg].EBO);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, model->geometries[g].subgeom[sg].indices.size(), GL_UNSIGNED_INT, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user