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.