This article is the second part of Parsing Blender 3D Files. If you have not read the first article of this series please do so to get a full understanding of this article.
When your application is parsing through the previously mentioned vector array of pointers to various Blender data blocks and the runtime pointer reaches a code of “OB” then your application is ready to parse a list of Blender Objects and their attributes.
A Blender Object contains the position, orientation, and other data that is common of all Blender Components. To parse a Blender Object you will need the SDNA information for a Blender Object (that was mentioned and built within the previous article). Using the header information of the data block fetch the SDNA index. Use the SDNA index and the previously built SDNA information to find the associate data type information for the data block the vector array iterator is currently pointing at.
Once you have the SDNA data type information check the name of the data type. If you find the name is equal to “Object” then the data block the iterator is pointing to is a Blender Object and we are ready to parse the data block.
Now at this point we have enough information within the SDNA information to build a Blender Object. If you look within the SDNA’s attribute map that we built earlier you can see all the attributes of a Blender Object and the data that is associated with each attribute. With the example below you can see the list of the Blender Object’s attributes. The attribute that is fully expanded within the debug watch window is an attribute named “data” which is a void pointer.
You can type out your Blender Object class using this information in any desired programming language. You can use the offset of each attribute to find the attribute’s data within the data block that the iterator is currently pointing to. For example to find the void pointer’s pointing address use the memory block with an offset of 296, just like below:
I recommend building a function that you can use with the SDNA information to fetch the offset with a given input parameter of the string variable name (for this example “*data”).
I also recommend using the Blender source code as a template to build your own class and or structures to contain the data that you are fetching from the data block.
After building the Blender Object you will need to track it within a map that is indexed by the old memory address of the child Blender Component that the parent Blender Object is pointing to. The void pointer “data” is the old memory address of the associated child Blender Component. So, if this Blender Object is associated with a Blender Lamp then “data” will have the old memory address of the Blender Lamp. The relationship between the two objects is one where the Blender Object describes the attributes that are common among all Blender Components like the location “loc”, orientation “rot”, etc. while the Blender Component describes the attributes that specific to that type of Blender Component.
Note some Blender Components are parsed before and after the list of Blender Objects. I tracked the Blender Components that was parsed before the list of Blender Objects in a temporary Blender Object that is stored within the map. When my application parsed the actual Blender Object I moved the stored information from the temporary to the actual and then deleted the temporary object from memory.
Once you are finished parsing the new Blender Object just increment the iterator to the next data block which should be the next Blender Object within the list, the next data attribute of the current Blender Object (like Solidify Modifier Data) or the next Blender Component (lamp “LA”, mesh “ME”, camera “CA”, etc).
- Parsing Blender 3D Files (*.blend) – (1 of 3)
- Parsing Blender 3D Files (*.blend) – (3 of 3) Linking Blender Objects and Components
- The mystery of the blend, The blender file-format explained by Jeroen Bakker
- Blender’s Python API Documentation
- Blender’s Source Code: folders makesdna and makesrna under source/blender.