project: COLLADA 2 BIN

Details

Program that converts geometric and animation 3D scene data, from a COLLADA "*.dae" file to a binary file, with a custom format.

  • current version: 1.0
  • last updated: February, 2019
Download source

src > visualscenes.cpp

View raw
#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);
  */
}