Hi,
This is my first post on this forum.
My current project is to write a c++ application for reading a .blend file. I have been successful until now. To test my application I render it in OpenGL. I have read the materials from a .blend file that contains one mesh with 6 materials attached to different faces. It works fine except that I can't get the order/index of the materials to match the face property "mat_nr" as I believe it's intended for.
So my questions are:
How to read the correct order of the material **mat property?
Is the mat_nr the correct index of the material attached to that the specific face?
Read .blend file materials
Moderators: jesterKing, stiv
Re: Read .blend file materials
My code is written like this when reading a mesh material list, this is obvious wrong, any one that can point me to the right direction? 

Code: Select all
void Mesh::parseMaterials(StructureDNA *sdna,
FileBlockHeader *fbh, std::vector<Material > *mat) {
if(fbh == 0 || totcol == 0)
return;
FileBlockHeader *mfbh = sdna->getFileBlock("**mat", fbh),
*next = 0, *prev = 0;
if(mfbh) {
printFields(mfbh, sdna);
next = sdna->getFileBlock("*next", mfbh);
prev = sdna->getFileBlock("*prev", mfbh);
}
int j = 0;
while(next) {
std::string colname = next->getString("id.name", sdna);
for (unsigned int i = 0; i < mat->size(); i++) {
if(colname == mat->at(i).name){
materials.push_back(&(mat->at(i)));
// printFields(next, sdna);
j++;
break;
}
}
next = sdna->getFileBlock("id.*next", next);
}
while(prev) {
std::string colname = prev->getString("id.name", sdna);
for (unsigned int i = 0; i < mat->size(); i++) {
if(colname == mat->at(i).name){
materials.push_back(&(mat->at(i)));
// printFields(prev, sdna);
j++;
break;
}
}
prev = sdna->getFileBlock("id.*prev", prev);
}
}
I'm not sure what code you use but I've read a lot of the data inside a .blend using FBT from GameKit. Check http://www.gamekit.org there's a lot of code there that does the same.
Nice you are correct, there is a lot of code there, I'll check it out and see if I can find something.sphaero wrote:I'm not sure what code you use but I've read a lot of the data inside a .blend using FBT from GameKit. Check http://www.gamekit.org there's a lot of code there that does the same.
I believe that there is something I don't understand though. It's about the material structure in the .blend file. The code you saw was developed by my self and I feel that I can have read the **mat variable in the wrong way.
My method:
- 1. First I read an integer from **mat. lets call the integer addr
2. Then I read the file-block in the position addr, that will give me *mat. This file-block becomes of the type LINK.
3. I would expect to have more than 2 pointers *next, and *prev to play around with at this point.(one mesh can have more than 2 materials). This is something I think is very confusing.
Some Ideas about my problem?
I think you are correct in that you might be wrong
However I'm not familiar with the data structure of materials by heart so I can't help you there. I think how AnimKit does could be of help: http://code.google.com/p/gamekit/source ... der.cpp#88

Nice, it is still confusing about the link type of the data structure but I think I have solved it now. I solved it by ignoring the structure type and read past the structure, and I read the data as it only would be integers. With the count of totcol(the amount of materials) and it worked! I know that my code are not documented at all but if anyone would be intrested in my complete solution here you go:
Thanks for the response sphaero 
Code: Select all
void Blender::Mesh::parseMaterials(StructureDNA *sdna,
FileBlockHeader *fbh, std::vector<Material > *mat) {
if(fbh == 0 || totcol == 0)
return;
FileBlockHeader *mfbh = sdna->getFileBlock("**mat", fbh);
if(mfbh) {
for (int i = 0; i < totcol; i++) {
int addr = mfbh->getInt(0, i, 4); // offset, position,
// This is a color fileblock
FileBlockHeader *color = sdna->getFileBlockByAddress(addr);
if(color == 0) return; // if no color found abort
// get the name of the material
std::string colname = color->getString("id.name", sdna);
for (unsigned int j = 0; j < mat->size(); j++) { // find the mat in global mats
if(colname == mat->at(j).name){ // a match
materials.push_back(&(mat->at(j)));// add the material
break;
}
}
}
}
}
