Program that converts geometric and animation 3D scene data, from a COLLADA "*.dae" file to a binary file, with a custom format.
#include "./funcs.hpp"
static bool flag_MAT4_TRANSPOSE= true;//TODO: extract further
void read_scene_node_transform(TiXmlElement* nodeNode, bindoc& docData, scene_node& currNode)
{
//read pos
TiXmlElement* translNode= nodeNode->FirstChildElement("translate");
//set to locRotScale by default
currNode.transf_type = scene_node::TRANS_LOCROTSCALE;
if(translNode!= NULL){
std::string translsid(translNode->Attribute("sid"));
if(translsid.compare("location")== 0)
vec3_from_node(translNode, currNode.pos);
}
//read rotations
TiXmlElement* rotNode= nodeNode->FirstChildElement("rotate");
int rii= 0;
while(rotNode!= NULL){
std::string rotsId(rotNode->Attribute("sid"));
if(rotsId.compare("rotationX")== 0)
{
currNode.rotOrder[rii]= 'x';
vec4_from_node(rotNode, currNode.rotx);
}
else if(rotsId.compare("rotationY")== 0)
{
currNode.rotOrder[rii]= 'y';
vec4_from_node(rotNode, currNode.roty);
}
else if(rotsId.compare("rotationZ")== 0)
{
currNode.rotOrder[rii]= 'z';
vec4_from_node(rotNode, currNode.rotz);
}
rii++;
rotNode= rotNode->NextSiblingElement("rotate");
}
//read scale
TiXmlElement* scaleNode= nodeNode->FirstChildElement("scale");
if(scaleNode!= NULL){
std::string scalesid(scaleNode->Attribute("sid"));
if(scalesid.compare("scale")== 0)
vec3_from_node(scaleNode, currNode.scale);
}
//ALT: read trans matrix
TiXmlElement* matrixNode= nodeNode->FirstChildElement("matrix");
if(matrixNode!= NULL){
std::string transsid(matrixNode->Attribute("sid"));
if(transsid.compare("transform")== 0)
{
//read trans matrix and set matrix trans type
currNode.transf_type = scene_node::TRANS_MATRIX;
mat4_from_node(matrixNode, currNode.transform, flag_MAT4_TRANSPOSE);
}
}
//choose trans matrix as default output trans type
currNode.switch_trans_type(scene_node::TRANS_MATRIX, true);
}
void read_scene_node_instance(TiXmlElement* nodeNode, bindoc& data, scene_node& currNode)
{
currNode.instance_type= SCENE_INSTANCE_TYPE::NONE;
for(uint32 ti= 0; ti< NUM_INST_TYPES; ti++){
TiXmlElement* instanceNode = nodeNode->FirstChildElement(instance_types[ti].c_str());
if(instanceNode == NULL) continue;
const char* urlAttr= instanceNode->Attribute("url");
if(urlAttr == NULL) continue;
currNode.instance_id= std::string(urlAttr);
switch(ti)
{
case 0:
currNode.instance_type= SCENE_INSTANCE_TYPE::GEOMETRY;
break;
case 1:
currNode.instance_type= SCENE_INSTANCE_TYPE::ARMATURE_CTRL;
break;
case 2:
currNode.instance_type= SCENE_INSTANCE_TYPE::LIGHT;
break;
}
}
//TODO: <instance_light url="#level_light_1-light"/>
}
void read_node_attrs(TiXmlElement* nodeNode, bindoc& docData, scene_node& currNode)
{
//read name
const char* nodeNameAttr= nodeNode->Attribute("name");
if(nodeNameAttr != NULL)
{
currNode.name= std::string(nodeNameAttr);
}
//read type
const char* nodeTypeAttr= nodeNode->Attribute("type");
if(nodeTypeAttr != NULL)
{
std::string nodeTypeStr= std::string(nodeTypeAttr);
//nodeTypeStr= std::tolower(nodeTypeStr, std::locale::classic());
if(nodeTypeStr.compare("NODE")== 0)
{
currNode.node_type= scene_node::TYPE_NODE;
}
else if(nodeTypeStr.compare("JOINT")== 0)
{
currNode.node_type= scene_node::TYPE_JOINT;
}
}
//read node id
const char* nodeIdAttr= nodeNode->Attribute("id");
if(nodeIdAttr != NULL)
{
currNode.nodeId= std::string(nodeIdAttr);
}
}
void read_scene_node(TiXmlElement* nodeNode, bindoc& docData, scene_node* parentNode)
{
scene_node& currNode= *(
(parentNode != NULL)
? parentNode->child_nodes.insert(parentNode->child_nodes.end(), scene_node())
: docData.scene.scene_nodes.insert(docData.scene.scene_nodes.end(), scene_node())
);
currNode.parent_node= parentNode;
//READ attributes
read_node_attrs(nodeNode, docData, currNode);
//READ transform information
read_scene_node_transform(nodeNode, docData, currNode);
//READ instance information
read_scene_node_instance(nodeNode, docData, currNode);
//try read armature ctrl instance
if(read_armature_ctrl(nodeNode, currNode, docData))
{
currNode.node_type = scene_node::TYPE_ARMATURE_DEF;
//return;
}
TiXmlElement* childNode= NULL;
for(childNode = nodeNode->FirstChildElement("node");
childNode != NULL;
childNode = childNode->NextSiblingElement("node")
){
read_scene_node(childNode, docData, &currNode);
}
}
void read_scene(TiXmlDocument* colladaDoc, bindoc& binDoc)
{
TiXmlElement* colladaDocNode= colladaDoc->RootElement();
TiXmlElement* sceneNode= colladaDocNode->FirstChildElement("library_visual_scenes")->FirstChildElement("visual_scene");
if(sceneNode == NULL) return;
//read name
const char* sceneNameAttr= sceneNode->Attribute("name");
if(sceneNameAttr != NULL)
{
binDoc.scene.name= std::string(sceneNameAttr);
}
for(TiXmlElement* nodeNode = sceneNode->FirstChildElement("node");
nodeNode != NULL;
nodeNode = nodeNode->NextSiblingElement("node")
){
read_scene_node(nodeNode, binDoc);
}
}
bool read_armature_joint_node(TiXmlElement* jointNode, armature_ctl& ctl, armature_joint& joint)
{
//type check - node must be JOINT always
const char* nodeTypeAttr= jointNode->Attribute("type");
if(nodeTypeAttr == NULL) return false;
std::string nodeTypeStr= std::string(nodeTypeAttr);
//nodeTypeStr= std::tolower(nodeTypeStr, std::locale::classic());
ASSERT(nodeTypeStr.compare("JOINT")== 0);
TiXmlElement* transMatrixNode= jointNode->FirstChildElement("matrix");
//read transform matrix
if(transMatrixNode!= NULL){
std::string translsId(transMatrixNode->Attribute("sid"));
if(translsId.compare("transform")== 0)
mat4_from_node(transMatrixNode, joint.transform, flag_MAT4_TRANSPOSE);
}
//read child joints
int chi= 0;
bool greatSuccess= true;
TiXmlElement* childJointNode= jointNode->FirstChildElement("node");
while(childJointNode!= NULL){
int chind= -1;
find_joint(ctl, childJointNode->Attribute("sid"), chind);
if(chind== -1) return false;
joint.child_joints.push_back(&ctl.joints[chind]);
ctl.joints[chind].parent_joint= &joint;
//read child node id and override the prev joint id
const char* jntIdAttr= childJointNode->Attribute("id");
if(jntIdAttr != NULL){
ctl.joints[chind].nodeId= std::string(jntIdAttr);
}
greatSuccess=
greatSuccess
&& read_armature_joint_node(childJointNode, ctl, ctl.joints[chind]);
childJointNode= childJointNode->NextSiblingElement("node");
chi++;
}
return greatSuccess;
}
bool read_armature_ctrl(TiXmlElement* armatureInstanceNode, scene_node& ctrlSceneNode, bindoc& docData)
{
//if(ctrlSceneNode.instance_type != SCENE_INSTANCE_TYPE::ARMATURE_CTRL) return;
int ctli=-1;
find_controller(ctrlSceneNode.name, docData, ctli);
if(ctli< 0) return false;
return true;
//armature_ctl& ctl= docData.armature_ctls[ctli];
/*
//find root armature node
TiXmlElement* rootArmatureJointNode= armatureInstanceNode->FirstChildElement("node");
//NOTE: Only working with one root joint element for now!
ASSERT(rootArmatureJointNode != NULL)
//find and set the root node
int ind= -1;
find_joint(ctl, rootArmatureJointNode->Attribute("sid"), ind);
ASSERT(ind> -1);
//read the root joint nodes tree
ctl.root_joint= &ctl.joints[ind];
return read_armature_joint_node(rootArmatureJointNode, ctl, *ctl.root_joint);
*/
}