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"
void write_string(FILE* binfile, const char* str, const uint32 len, const char* tag= NULL);
template <typename T> void write_number(FILE* binfile, const T* data, const uint32 len, const char* tag= NULL);
void write_materials(FILE* binfile, const std::set<std::string>& materials);
void write_mesh_geometries(FILE* binfile, const std::vector<mesh_geometry>& geoms);
void write_mesh_geometry(FILE* binfile, const mesh_geometry& geom);
void write_animations(FILE* binfile, const std::vector<animation>& animations);
void write_controllers(FILE* binfile, const bindoc& binDoc);
void write_scene(FILE* binfile, const scene_data& scene);
void write_bindoc(FILE* binFile, bindoc& binDoc)
{
//write materials list
write_materials(binFile, binDoc.materials);
//write geometries
write_mesh_geometries(binFile, binDoc.meshes);
//write animations
write_animations(binFile, binDoc.animations);
//write controllers
write_controllers(binFile, binDoc);
//write scene
write_scene(binFile, binDoc.scene);
}
void write_string(FILE* binfile, const char* str, const uint32 len, const char* tag)
{
if(tag != NULL) printf("[%s](%s)[%d];\n", tag, str, len);
fwrite((void*)&len, sizeof(uint32), 1, binfile);
fwrite((void*)str, sizeof(char), len, binfile);
}
template <typename T> void write_number(FILE* binfile, const T* data, const uint32 len, const char* tag)
{
if(tag != NULL) printf("[%s](%f...)[%d];\n", tag, (float)data[0], len);
fwrite((void*)data, sizeof(T), len, binfile);
}
void write_controller(FILE* binfile, const bindoc& binDoc, const armature_ctl& ctl)
{
int skinMeshIndex= -1;
find_mesh(ctl.skin_source, binDoc, skinMeshIndex);
ASSERT(skinMeshIndex != -1);
const mesh_geometry& skinMesh= binDoc.meshes[skinMeshIndex];
//write name
write_string(binfile, ctl.name.c_str(), ctl.name.size(), ctl.name.c_str());
//write ctrlId
write_string(binfile, ctl.ctrlId.c_str(), ctl.ctrlId.size(), ctl.ctrlId.c_str());
//write skin mesh source id
write_string(binfile, ctl.skin_source.c_str(), ctl.skin_source.size(), ctl.skin_source.c_str());
//write bind shape matrix
write_number<float>(binfile, &ctl.bind_shape_matrix.e00, 16, "bindmat");
//write the number of armature joints
uint32 numJoints= ctl.joints.size();
write_number<uint32>(binfile, &numJoints, 1, "numjoints");
//write the joint hierarchy array
/*for(uint32 ci= 0; ci< numJoints; ci++){
const armature_joint& jnt= ctl.joints[ci];
//write number of child joints
uint32 numChiJoints= jnt.child_joints.size();
write_number<uint32>(binfile, &numChiJoints, 1, "numchijnt");
//C child indices
for(uint32 cji= 0; cji< numChiJoints; cji++){
uint32 chjnti= jnt.child_joints[cji]->joint_arr_index;
write_number<uint32>(binfile, &chjnti, 1);
}
}*/
//ARMATURE JOINT DATA
for(uint32 ci= 0; ci< numJoints; ci++){
const armature_joint& jnt= ctl.joints[ci];
//write joint name
write_string(binfile, jnt.name.c_str(), jnt.name.size(), jnt.name.c_str());
//write joint node id
write_string(binfile, jnt.nodeId.c_str(), jnt.nodeId.size(), jnt.nodeId.c_str());
//write transform matrix
//write_number<float>(binfile, &jnt.transform.e00, 16);
//write inverse transform
write_number<float>(binfile, &jnt.inv_bind_transform.e00, 16);
}
//ARMATURE-SKIN DATA
const num1D_data& awghts= ctl.vertex_joint_weights;
const num1D_data& aassoc= ctl.vertex_joint_assoc;//*currMesh.armature->vertex_joint_assoc;
uint32 wjstride= 3;
uint32 nvert= skinMesh.vertices.size();//(ctl.vertex_joint_weights.size/wjstride)/sizeof(float);
uint32 wjsize= nvert*wjstride;//why???
write_number<uint32>(binfile, &wjsize, 1, "nvert*3");
write_number<uint32>(binfile, &wjstride, 1, "stride=3");
//write assoc array to file
for(uint32 vi= 0; vi< nvert; vi++){
uint32 asi= skinMesh.vertices[vi].indices[0];//pos index is ident vertex index
//write joint indices for vertex
for(uint32 ji= 0; ji< wjstride; ji++){
int assoc_ji= ((int*)aassoc.num_data)[asi*(wjstride*2)+ ji*2];
write_number<int>(binfile, &assoc_ji, 1);
}
}
//write weights array to file
for(uint32 vi= 0; vi< nvert; vi++){
uint32 asi= skinMesh.vertices[vi].indices[0];//pos index is ident vertex index
for(uint32 wi= 0; wi< wjstride; wi++){
int assoc_wi= ((int*)aassoc.num_data)[asi*(wjstride*2)+ wi*2+1];
float weightVal= -1.0f;
if(assoc_wi != -1){
weightVal= ((float*)awghts.num_data)[assoc_wi];
}
write_number<float>(binfile, &weightVal, 1);
}
}
}
void write_controllers(FILE* binfile, const bindoc& binDoc)
{
const std::vector<armature_ctl>& controllers= binDoc.armature_ctls;
//write number of controllers
uint32 numCtls= controllers.size();
write_number<uint32>(binfile, &numCtls, 1, "numctls");
//write controllers
for(uint32 ci=0; ci< numCtls; ci++){
write_controller(binfile, binDoc, controllers[ci]);
}
}
void write_animation(FILE* binfile, const animation& anim)
{
ASSERT(anim.animType == ANIMATION_TYPE::TRANSFORM);//additional validation
//write animation id
write_string(binfile, anim.animId.c_str(), anim.animId.size(), anim.animId.c_str());
//write animation target id
write_string(binfile, anim.targetId.c_str(), anim.targetId.size(), anim.targetId.c_str());
//write number of keyframes
uint32 nKeyFrames= anim.num_keyframes;
write_number<uint32>(binfile, &nKeyFrames, 1, "animnkeys");
//write keyframe timestamps
for(uint32 fi=0; fi< nKeyFrames; fi++){
float keyframe_= anim.timestamps[fi];
write_number<float>(binfile, &keyframe_, 1);
}
//write keyframe transforms
for(uint32 fi=0; fi< nKeyFrames; fi++){
const math::MAT4& transform_= anim.transforms[fi];
write_number<float>(binfile, &transform_.e00, 16);
}
}
void write_animations(FILE* binfile, const std::vector<animation>& animations)
{
//write number of animations
uint32 numAnims= animations.size();
write_number<uint32>(binfile, &numAnims, 1, "numanims");
//write animations
for(uint32 ai= 0; ai< numAnims; ai++)
{
write_animation(binfile, animations[ai]);
}
}
void write_scene_node(FILE* binfile, const scene_node& node)
{
//write type
int nodetype= (int)node.node_type;
write_number<int>(binfile, &nodetype, 1);
//write name
write_string(binfile, node.name.c_str(), node.name.size(), node.name.c_str());
//write id
write_string(binfile, node.nodeId.c_str(), node.nodeId.size(), node.nodeId.c_str());
//write instance type
int insttype= (int)node.instance_type;
write_number<int>(binfile, &insttype, 1);
//write instance id
write_string(binfile, node.instance_id.c_str(), node.instance_id.size());
//write transform matrix
write_number<float>(binfile, &node.transform.e00, 16, "nodetransf");
//write num of child nodes
uint32 nchinodes= node.child_nodes.size();
write_number<uint32>(binfile, &nchinodes, 1, "nodenchild");
//write child nodes
for(uint32 chi=0; chi< nchinodes; chi++)
{
write_scene_node(binfile, node.child_nodes[chi]);
}
}
void write_scene(FILE* binfile, const scene_data& scene)
{
//write scene name
write_string(binfile, scene.name.c_str(), scene.name.size(), "scenename");
//write number of scene nodes
uint32 nnodes= scene.scene_nodes.size();
write_number<uint32>(binfile, &nnodes, 1, "scenennodes");
//write scene nodes
for(uint32 si= 0; si< nnodes; si++)
{
write_scene_node(binfile, scene.scene_nodes[si]);
}
}
void write_materials(FILE* binfile, const std::set<std::string>& materials)
{
uint32 matNum= materials.size();
write_number<uint32>(binfile, &matNum, 1, "nmats");
std::set<std::string>::iterator it;
for (it = materials.begin(); it != materials.end(); ++it)
{
std::string matName;
size_t spos= it->find("-material", 0);
matName= it->substr(0, spos);
write_string(binfile, matName.c_str(), matName.size(), "matname");
}
}
void write_mesh_geometries(FILE* binfile, const std::vector<mesh_geometry>& geoms)
{
//write number of geometries
uint32 gsize= (uint32)geoms.size();
write_number<uint32>(binfile, &gsize, 1, "nmeshes");
//write geometries
for(uint32 gi= 0; gi< geoms.size(); gi++){
write_mesh_geometry(binfile, geoms[gi]);
}
}
void write_mesh_geometry(FILE* binfile, const mesh_geometry& geom)
{
const raw_meshdata& meshdata= geom.raw;
//write name
write_string(binfile, geom.name.c_str(), geom.name.size(), "gname");
//write id
write_string(binfile, geom.meshId.c_str(), geom.meshId.size(), "gid");
//gen sources offset map
uint32 nsrc= meshdata.sources.size();
uint32 ninp= 1;
GLenum primType= -1;
uint32 sourceSemOffsetMap[nsrc];
const uint32* inputSemantMap= NULL;
//Note: Assuming that every prim group is like the first group. Atleast do a check maybe!
{
//determine primitive type
primType= meshdata.prim_groups[0].primitive;
//determine semantics map
inputSemantMap= &meshdata.prim_groups[0].input_semantics[0];
//determine number of inputs
ninp= meshdata.prim_groups[0].inputs_count;
for(uint32 si= 0; si< nsrc; si++){
for(uint32 ini= 0; ini< meshdata.prim_groups[0].input_semantics.size(); ini++){
if(meshdata.prim_groups[0].input_semantics[ini] == meshdata.sources[si].semantic)
sourceSemOffsetMap[si]= ini;
}
}
}
//write primitive type
write_number<GLenum>(binfile, &primType, 1, "gprim");
//write number of sources
write_number<uint32>(binfile, &nsrc, 1, "gnsrc");
//write number of inputs
write_number<uint32>(binfile, &ninp, 1, "gninp");
//write semantics map
ASSERT(inputSemantMap != NULL);
write_number<uint32>(binfile, inputSemantMap, ninp, "ginpsem");
//write sources
for(uint32 si= 0; si< nsrc; si++){
const num1D_data& sourceData= meshdata.sources[si];
//assume numeric array source data = correct assumption
/*uint32 elSize= (sourceData.gltype== GL_FLOAT)
? sizeof(float)
: (sourceData.gltype== GL_INT)? sizeof(int): 1;*/
uint32 numEl= geom.vertices.size()*sourceData.stride;
write_number<uint32>(binfile, &sourceData.semantic, 1, "srcsem");//semantic
write_number<GLenum>(binfile, &sourceData.gltype, 1, "srcgltype");//type
write_number<uint32>(binfile, &numEl, 1, "srcnel");//number of elements
write_number<uint32>(binfile, &sourceData.stride, 1, "srcstride");//stride
int indi= sourceSemOffsetMap[si];
if(sourceData.gltype== GL_FLOAT){
float* fdata= (float*)sourceData.data();
for(uint32 ii= 0; ii< geom.vertices.size(); ii++){
const vertex* vert= &geom.vertices[ii];
for(uint32 gi= 0; gi< sourceData.stride; gi++){
float val= fdata[vert->indices[indi]*sourceData.stride+gi];
write_number<float>(binfile, &val, 1, "f");
}
}
}
else if(sourceData.gltype== GL_INT){
int* idata= (int*) sourceData.data();
for(uint32 ii= 0; ii< geom.vertices.size(); ii++){
const vertex* vert= &geom.vertices[ii];
for(uint32 gi= 0; gi< sourceData.stride; gi++){
int val= idata[vert->indices[indi]*sourceData.stride+gi];
write_number<int>(binfile, &val, 1, "i");
}
}
}
}
//write material ref
for(uint32 ii= 0; ii< geom.vertices.size(); ii++)
{
const vertex* vert= &geom.vertices[ii];
int matId= vert->material_id;
write_number<int>(binfile, &matId, 1);
}
//write indices
uint32 numIndices= geom.indices.size();
write_number<uint32>(binfile, &numIndices, 1, "nindic");
write_number<uint32>(binfile, &geom.indices[0], numIndices, "indic");
//write edges
uint32 numEdges= geom.edges.size();
write_number<uint32>(binfile, &numEdges, 1, "nedges");
for(uint32 ei= 0; ei< numEdges; ei++)
{
write_number<int>(binfile, &geom.edges[ei].posit[0], 2);
}
//write triangles
uint32 numTriangle= geom.triangles.size();
write_number<uint32>(binfile, &numTriangle, 1, "ntriag");
for(uint32 ti= 0; ti< numTriangle; ti++)
{
write_number<int>(binfile, &geom.triangles[ti].posit[0], 3);
write_number<int>(binfile, &geom.triangles[ti].edges[0], 3);
}
}