With Assimp what is a bone's parent

I can’t seem to find anything relating to parent except mTransformation in node. Is each node a set of siblings? I guess then things would make sense.

This is what I have come up with so far

void MeshHolder::loadmodel(string path) {
	Assimp::Importer importer;
	const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
	if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
		errorType = importer.GetErrorString();
		error = true;
		return;
	}
	error = false;
	directory = path.substr(0, path.find_last_of("/"));
	processNode(scene->mRootNode, scene);
	aiMesh* parMesh = scene->mMeshes[0];
	Bone temp;
	vector<Bone> structure;
	for (unsigned int i = 0; i < parMesh->mNumBones; i++) {
		aiBone* bone = parMesh->mBones[i];
		temp.setMatrix(bone->mOffsetMatrix);
		temp.name = bone->mName.C_Str();
		temp.refNum = i;
		structure.push_back(temp);
	}
	Bone stor;
	readSkeleton(stor, scene->mRootNode, structure);
}

bool MeshHolder::readSkeleton(Bone& boneOut, aiNode* node, vector<Bone>& structureRef) {
	bool found = false;
	int idx;
	for (int i = 0; i < structureRef.size(); i++) {
		if (node->mName.C_Str() == structureRef.at(i).name) {
			found = true;
			idx = i;
			break;
		}
	}
	if (found) {
		boneOut = structureRef.at(idx);
		for (int i = 0; i < node->mNumChildren; i++) {
			Bone child;
			readSkeleton(child, node->mChildren[i], structureRef);
			boneOut.children.push_back(child);
		}
		return true;
	}
	else {
		for (int i = 0; i < node->mNumChildren; i++) {
			if (readSkeleton(boneOut, node->mChildren[i], structureRef)) {
				return true;
			}

		}
	}
	return false;
}

Bone class;

#include <vector>
#include <string>
#include <ofMain.h>
#include "assimp/scene.h"
#include "assimp/postprocess.h"
using namespace std;
class Bone
{
public:
	Bone();
	void setMatrix(const aiMatrix4x4& from);
	vector<unsigned int> induces;
	vector<float> weights;
	string name;
	glm::mat4 offsetMat;
	int refNum;
	vector<Bone> children;
private:
	glm::mat4 Assimp2Glm(const aiMatrix4x4& from);
	aiMatrix4x4 Glm2Assimp(const glm::mat4& from);
	
};

#include "Bone.h"

Bone::Bone() {
    name = "";
    refNum = 0;
    offsetMat = glm::mat4(1.0);
}

void Bone::setMatrix(const aiMatrix4x4& from) {
    offsetMat = Assimp2Glm(from);
}

glm::mat4 Bone::Assimp2Glm(const aiMatrix4x4& from)
{
    return glm::mat4(
        (double)from.a1, (double)from.b1, (double)from.c1, (double)from.d1,
        (double)from.a2, (double)from.b2, (double)from.c2, (double)from.d2,
        (double)from.a3, (double)from.b3, (double)from.c3, (double)from.d3,
        (double)from.a4, (double)from.b4, (double)from.c4, (double)from.d4
    );
}
aiMatrix4x4 Bone::Glm2Assimp(const glm::mat4& from)
{
    return aiMatrix4x4(from[0][0], from[1][0], from[2][0], from[3][0],
        from[0][1], from[1][1], from[2][1], from[3][1],
        from[0][2], from[1][2], from[2][2], from[3][2],
        from[0][3], from[1][3], from[2][3], from[3][3]
    );
}

I just have to work it out for the meshes;

@tunnelman,
I only have have the tree & nodes consept from other situations.
The setup would hardly make sense unless

class node{
relevant member values,
vector(node-ref of siblings)
node-ref parent,
}
The class node can be used for iteration through the full tree, where you also need to have a conseptual node with a null parent, aka a root. You may have to spent some efforts on figuring out how to iterate ‘freely’ between two nodes. If you store nodes in a vector, you’ll have one linear order that likly does not make much sense closer that ie some nodes sortorder mixX->maxX, minY->maxY, minZ->maxZ

relevant member values are the matrices associated. From hip: ideally one (local coordinates) is needed, the one you multiply to the global matrix before drawing the node.

I wrote:
“If you store nodes in a vector, you’ll have one linear order that likly does not make much sense closer that ie some nodes sortorder mixX->maxX, minY->maxY, minZ->maxZ”

This is probably misleading.
There is a structural order that follows
it’s recoursive.
current_node = root ( == first node)
current_node = current_node.first_child ( == next node)
now third node is again current_node.first_child , not root.second_child
The snag is, that there’s a lot of if-testing: is there a next node, is node a leaf-node, is node null.
A d2-drawn tree will follow the contour of the tree. It’s also kind of circular. The iteration needs the first and the one-passed-last node going forward (the next uncle seen from the start.childrens perspective).

The perk of this order/iteration is, that it works on any node, not just a full traverse.
When it comes to adding and deleting nodes and such, none of it is uncapable of fooling a fair programmer.

…edit…
come to think of the parent_ref. Should it be superflous it the instance of the class that contains the children IS the parent, by rationale? You may come to handle a single node without context where node->parent makes sense. I’m not sure if this applies to your doubt … or weather I’ve used a superflous member in my code.