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
@ -77,6 +77,8 @@ std::unique_ptr<Model> LoaderDFF::loadFromMemory(char *data)
|
|||||||
|
|
||||||
size_t matI = 0;
|
size_t matI = 0;
|
||||||
materiallistsec.getNextChildSection(matI);
|
materiallistsec.getNextChildSection(matI);
|
||||||
|
|
||||||
|
geometryStruct.materials.resize(materialList.nummaterials);
|
||||||
|
|
||||||
for (size_t m = 0; m < materialList.nummaterials; ++m) {
|
for (size_t m = 0; m < materialList.nummaterials; ++m) {
|
||||||
auto materialsec = materiallistsec.getNextChildSection(matI);
|
auto materialsec = materiallistsec.getNextChildSection(matI);
|
||||||
@ -84,10 +86,11 @@ std::unique_ptr<Model> LoaderDFF::loadFromMemory(char *data)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto material = materialsec.readStructure<RW::BSMaterial>();
|
auto material = materialsec.readStructure<RW::BSMaterial>();
|
||||||
|
geometryStruct.materials[m].textures.resize(material.numtextures);
|
||||||
|
|
||||||
size_t texI = 0;
|
size_t texI = 0;
|
||||||
materialsec.getNextChildSection(texI);
|
materialsec.getNextChildSection(texI);
|
||||||
|
|
||||||
for (size_t t = 0; t < material.numtextures; ++t) {
|
for (size_t t = 0; t < material.numtextures; ++t) {
|
||||||
auto texsec = materialsec.getNextChildSection(texI);
|
auto texsec = materialsec.getNextChildSection(texI);
|
||||||
auto texture = texsec.readStructure<RW::BSTexture>();
|
auto texture = texsec.readStructure<RW::BSTexture>();
|
||||||
@ -103,13 +106,44 @@ std::unique_ptr<Model> LoaderDFF::loadFromMemory(char *data)
|
|||||||
textureName = namesec.raw();
|
textureName = namesec.raw();
|
||||||
alphaName = alphasec.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
|
// OpenGL buffer stuff
|
||||||
glGenBuffers(1, &geometryStruct.VBO);
|
glGenBuffers(1, &geometryStruct.VBO);
|
||||||
glGenBuffers(1, &geometryStruct.EBO);
|
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)
|
size_t buffsize = (geometryStruct.vertices.size() * sizeof(float) * 3)
|
||||||
+ (geometryStruct.texcoords.size() * sizeof(float) * 2)
|
+ (geometryStruct.texcoords.size() * sizeof(float) * 2)
|
||||||
@ -162,9 +196,22 @@ std::unique_ptr<Model> LoaderDFF::loadFromMemory(char *data)
|
|||||||
indicies,
|
indicies,
|
||||||
GL_STATIC_DRAW
|
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
|
// Add it
|
||||||
model->geometries.push_back(geometryStruct);
|
model->geometries.push_back(geometryStruct);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,17 @@ public:
|
|||||||
std::string name;
|
std::string name;
|
||||||
std::string alphaName;
|
std::string alphaName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Material {
|
||||||
|
std::vector<Texture> textures;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubGeometry {
|
||||||
|
GLuint EBO;
|
||||||
|
size_t material;
|
||||||
|
std::vector<uint32_t> indices;
|
||||||
|
};
|
||||||
|
|
||||||
struct Geometry {
|
struct Geometry {
|
||||||
GLuint VBO, EBO;
|
GLuint VBO, EBO;
|
||||||
|
|
||||||
@ -28,7 +39,8 @@ public:
|
|||||||
std::vector<RW::BSTVector3> vertices;
|
std::vector<RW::BSTVector3> vertices;
|
||||||
std::vector<RW::BSTVector3> normals;
|
std::vector<RW::BSTVector3> normals;
|
||||||
|
|
||||||
std::vector<Texture> textures;
|
std::vector<Material> materials;
|
||||||
|
std::vector<SubGeometry> subgeom;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Geometry> geometries;
|
std::vector<Geometry> geometries;
|
||||||
|
@ -33,6 +33,8 @@ namespace RW
|
|||||||
|
|
||||||
SID_HAnimPLG = 0x011E,
|
SID_HAnimPLG = 0x011E,
|
||||||
|
|
||||||
|
SID_BinMeshPLG = 0x50E,
|
||||||
|
|
||||||
SID_NodeName = 0x0253F2FE
|
SID_NodeName = 0x0253F2FE
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -166,6 +168,19 @@ namespace RW
|
|||||||
uint16_t unknown;
|
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)
|
* Texture Dictionary Structures (TXD)
|
||||||
*/
|
*/
|
||||||
@ -284,6 +299,11 @@ namespace RW
|
|||||||
return *reinterpret_cast<T*>(data+offset+sizeof(BSSectionHeader)+internalOffset);
|
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()
|
char* raw()
|
||||||
{
|
{
|
||||||
return data + offset + sizeof(BSSectionHeader);
|
return data + offset + sizeof(BSSectionHeader);
|
||||||
|
@ -242,11 +242,6 @@ void render()
|
|||||||
// std::cout << "Rendering " << modelname << std::endl;
|
// std::cout << "Rendering " << modelname << std::endl;
|
||||||
|
|
||||||
for (size_t g = 0; g < model->geometries.size(); g++) {
|
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.
|
// 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);
|
glm::quat rot(-obj.rotW, obj.rotX, obj.rotY, obj.rotZ);
|
||||||
@ -255,15 +250,27 @@ void render()
|
|||||||
matrixModel = glm::scale(matrixModel, glm::vec3(obj.scaleX, obj.scaleY, obj.scaleZ));
|
matrixModel = glm::scale(matrixModel, glm::vec3(obj.scaleX, obj.scaleY, obj.scaleZ));
|
||||||
matrixModel = matrixModel * glm::mat4_cast(rot);
|
matrixModel = matrixModel * glm::mat4_cast(rot);
|
||||||
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(matrixModel));
|
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(matrixModel));
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, model->geometries[g].VBO);
|
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(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));
|
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, (void*)(model->geometries[g].vertices.size() * sizeof(float) * 3));
|
||||||
glEnableVertexAttribArray(posAttrib);
|
glEnableVertexAttribArray(posAttrib);
|
||||||
glEnableVertexAttribArray(texAttrib);
|
glEnableVertexAttribArray(texAttrib);
|
||||||
|
|
||||||
|
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].triangles.size() * 3, GL_UNSIGNED_SHORT, NULL);
|
glDrawElements(GL_TRIANGLES, model->geometries[g].subgeom[sg].indices.size(), GL_UNSIGNED_INT, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user