As I’ve written before: loading and displaying model on a isometric game level is a first goal. So let’s have a look into Python scripts loading Blender cubic models and into resultant JSON files structure. The code is here https://github.com/adamskopl/cubicforest/tree/master/cubicLoader.

The code’s structure reflects the structure of the model:

  • cubicLoader.py
  • cubicModel.py
  • cubicCubesGroup.py
  • cubicCube.py

Loader makes an instance of a Model and invokes loadGroups.

"""
cubicModel.py
"""
    def loadGroups(self):
        """
        Fill groups list with CubesGroup objects.
        """
        scene = bpy.data.scenes[0]
        sceneGroups = bpy.data.groups
        for sGroup in sceneGroups:
            groupName = sGroup.name
            groupCubes = sGroup.objects
            cubicGroup = cubicCubesGroup.CubesGroup(groupName)
            cubicGroup.loadCubes(groupCubes)
            self.groups.append(cubicGroup)

Having in mind that maybe I’ll want to divide model into groups (e.g. for simple animation purposed), loading starts with reading them:

sceneGroups = bpy.data.groups

The bpy object is generated by Blender. Next the group loads its cubes and the result is appended to the groups collection.

"""
cubicCubesGroup.py
"""
    def loadCubes(self, groupCubes):
        """
        Fill cubes list with objects from groupCubes list.
        """
        for groupCube in groupCubes:
            cube = cubicCube.Cube(groupCube.name)
            cube.setPos(groupCube.location)
            cube.setRot(groupCube.rotation_euler)
            cube.setCol(groupCube.data.materials[0].name)
            self.cubes.append(cube)

The Cube class is filled with data:

  • position
  • rotation
  • color

The location, rotation_euler and data.materials[0].name are provided by Blender. I’m saving material’s name, which will be later used to indicate the texture needed to render cube.

"""
cubicCube.py
"""
class Cube:
    """
    Class defining model's cube.

    Blender's equivalent: Cube Object.
    """
    def __init__(self, name):
        """ x """
        self.name = name
        self.pos = Vector()
        self.rot = Euler()

    def setPos(self, pos):
        self.pos = pos

    def setRot(self, rot):
        self.rot = rot

    def setCol(self, colName):
        self.colName = colName

Looks simple but it took some time to figure out how to extract needed data from the Blender’s scene.

Next step is to save the model as a JSON file:

"""
cubicLoader.py
"""
    def saveModel(self, fStart, fEnd):
        currentDir=os.path.dirname(os.path.abspath(__file__))
        config = configparser.ConfigParser()
        config.read(currentDir + "/config.ini")
        modelJson = self.model.toJson(fStart, fEnd)
        jsonData = simplejson.dumps(modelJson)
        fd = open(config['Paths']['writePath'] + '/' + self.modelName + ".json", "w")
        fd.write(jsonData)
        fd.close
"""
cubicModel.py
"""
    def toJson(self, fStart, fEnd):
        scene = bpy.data.scenes[0]
        modelDict = dict()
        framesList = list()
        for frameNum in range(fStart, fEnd+1):
            scene.frame_set(frameNum)
            frameDict = dict()
            groupsList = list()
            for frameGroup in self.groups:
                groupDict = frameGroup.toJson()
                groupsList.append(groupDict)
            frameDict["number"] = frameNum
            frameDict["groups"] = groupsList
            framesList.append(frameDict)
        modelDict["name"] = self.name
        modelDict["frames"] = framesList
        return modelDict
"""
cubicCubesGroup.python
"""
    def toJson(self):
        groupDict = dict()
        cubesList = list()
        for c in self.cubes:
            cubeDict = c.toJson()
            cubesList.append(cubeDict)
        groupDict["name"] = self.name
        groupDict["cubes"] = cubesList
        return groupDict
"""
cubicCube.py
"""
    def toJson(self):
        cubeDict = dict()

        posDict=dict()
        posDict["x"] = self.pos.x
        posDict["y"] = self.pos.y
        posDict["z"] = self.pos.z

        rotDict=dict()
        rotDict["x"] = self.rot.x
        rotDict["y"] = self.rot.y
        rotDict["z"] = self.rot.z

        cubeDict["name"] = self.name
        cubeDict["pos"] = posDict
        cubeDict["rot"] = rotDict
        cubeDict["colName"] = self.colName
        return cubeDict

Cubes are converted to JSON, added to the groups, which are also converted to JSON and passed to the model. Every part has its own toJson function.

Here’s the result file with data describing a model:

  • named ‘prize’
  • composed of 3x3x3=27 cubes
  • one frame, one group
{
  "name": "prize",
  "frames": [
    {
      "number": 1,
      "groups": [
        {
          "name": "Group",
          "cubes": [
            {
              "name": "Cube.027",
              "colName": "red",
              "pos": {
                "z": 7,
                "x": -1,
                "y": 0
              },
              "rot": {
                "z": 0,
                "x": 0,
                "y": 0
              }
            },
            {
              "name": "Cube.026",
              "colName": "red",
              "pos": {
                "z": 7,
                "x": 1,
                "y": 0
              },
              "rot": {
                "z": 0,
                "x": 0,
                "y": 0
              }
            },
            {
              "name": "Cube.025",
              "colName": "red",
              "pos": {
                "z": 7,
                "x": 0,
                "y": 0
              },
              "rot": {
                "z": 0,
                "x": 0,
                "y": 0
              }
            },
            {
              "name": "Cube.024",
              "colName": "red",
              "pos": {
                "z": 6,
                "x": 0,
                "y": 0
              },
              "rot": {
                "z": 0,
                "x": 0,
                "y": 0
              }
            },
            

           ...
           
            
          ]
        }
      ]
    }
  ]
}