Skip to content

Instantly share code, notes, and snippets.

@understar
Forked from praeclarum/n3mtodae.c
Created April 26, 2014 08:48

Revisions

  1. @praeclarum praeclarum created this gist Jan 21, 2012.
    230 changes: 230 additions & 0 deletions n3mtodae.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,230 @@
    #include <sys/stat.h>
    #include <sys/mman.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>

    struct xyz
    {
    float x, y, z;
    };

    struct uv
    {
    float u, v;
    };

    struct triangle
    {
    unsigned short a, b, c;
    };

    struct source
    {
    int number_of_verts;

    struct xyz *xyz_coords;
    struct uv *uv_coords;
    };

    struct material
    {
    int number_of_tris;
    int source_index;

    struct triangle *tris;
    };

    struct model
    {
    int bucket_levels;
    int number_of_sources;
    int number_of_materials;

    struct source *sources;
    struct material *materials;
    };

    int open_n3m (struct model *m, void *data)
    {
    char *magic = (char*)data;
    printf("magic: %c%c%c\n", magic[0], magic[1], magic[2]);
    if (magic[0] != 'N' || magic[1] != '3' || magic[2] != 'M') {
    return -1;
    }

    char version = magic[3];
    printf("version: %c\n", version);

    int *header = (int*)data;
    m->number_of_sources = header[1];
    m->number_of_materials = header[2];
    printf("number_of_sources: %d\n", m->number_of_sources);
    printf("number_of_materials: %d\n", m->number_of_materials);

    m->sources = calloc(m->number_of_sources, sizeof(struct source));
    m->materials = calloc(m->number_of_materials, sizeof(struct material));

    int i = 0;
    for (i = 0; i < m->number_of_sources; i++) {
    struct source *s = &m->sources[i];

    int offset = i * 2 + 3;

    int data_offset = header[offset];
    s->number_of_verts = header[offset + 1];

    printf("data_offset: %d\n", data_offset);
    printf("source[%d].number_of_verts: %d\n", i, s->number_of_verts);

    s->xyz_coords = (struct xyz*)((char*)data + data_offset);
    s->uv_coords = (struct uv*)((char*)data + data_offset + s->number_of_verts * 12);
    }

    for (i = 0; i < m->number_of_materials; i++) {
    struct material *mat = &m->materials[i];

    int offset = m->number_of_sources * 2 + i * 4 + 3;

    int indices_offset = header[offset];

    mat->number_of_tris = header[offset + 1];
    mat->source_index = header[offset + 2];
    mat->tris = (struct triangle*)((char*)data + indices_offset);

    printf("material[%d].number_of_tris: %d\n", i, mat->number_of_tris);
    printf("material[%d].source_index: %d\n", i, mat->source_index);
    }

    return 0;
    }

    int save_dae (struct model *m, FILE *f)
    {
    fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n");
    fprintf(f, "<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">\n");
    fprintf(f, " <asset>\n");
    fprintf(f, " <contributor>\n");
    fprintf(f, " <authoring_tool>n3mtodae</authoring_tool>\n");
    fprintf(f, " </contributor>\n");
    fprintf(f, " <created>2012-01-21T04:10:34Z</created>\n");
    fprintf(f, " <modified>2012-01-21T04:10:34Z</modified>\n");
    fprintf(f, " <unit meter=\"0.0254000\" name=\"inch\" />\n");
    fprintf(f, " <up_axis>X_UP</up_axis>\n");
    fprintf(f, " </asset>\n");

    fprintf(f, " <library_visual_scenes>\n");
    fprintf(f, " <visual_scene id=\"ID1VISUALSCENE\">\n");
    fprintf(f, " <node name=\"n3mtodae\">\n");
    int i = 0;
    for (i = 0; i < m->number_of_materials; i++) {
    struct material *mat = &m->materials[i];

    fprintf(f, " <instance_geometry url=\"#ID%pGEOMETRY\">\n", mat);

    fprintf(f, " <bind_material>\n");
    fprintf(f, " <technique_common>\n");
    fprintf(f, " <instance_material symbol=\"Material2\" target=\"#ID4\">\n");
    fprintf(f, " <bind_vertex_input semantic=\"UVSET0\" input_semantic=\"TEXCOORD\" input_set=\"0\" />\n");
    fprintf(f, " </instance_material>\n");
    fprintf(f, " </technique_common>\n");
    fprintf(f, " </bind_material>\n");

    fprintf(f, " </instance_geometry>\n");
    }
    fprintf(f, " </node>\n");
    fprintf(f, " </visual_scene>\n");
    fprintf(f, " </library_visual_scenes>\n");

    fprintf(f, " <library_geometries>\n");
    for (i = 0; i < m->number_of_materials; i++) {
    struct material *mat = &m->materials[i];
    struct source *src = &m->sources[mat->source_index];

    fprintf(f, " <geometry id=\"ID%pGEOMETRY\">\n", mat);
    fprintf(f, " <mesh>\n");

    fprintf(f, " <source id=\"ID%pSOURCE\">\n", src->xyz_coords);
    fprintf(f, " <float_array id=\"ID%pARRAY\" count=\"%d\">", src->xyz_coords, src->number_of_verts * 3);
    int j = 0;
    for (j = 0; j < src->number_of_verts; j++) {
    fprintf(f, "%g %g %g ", src->xyz_coords[j].x, src->xyz_coords[j].y, src->xyz_coords[j].z);
    }
    fprintf(f, "</float_array>\n");
    fprintf(f, " <technique_common>\n");
    fprintf(f, " <accessor count=\"%d\" source=\"#ID%pARRAY\" stride=\"3\">\n", src->number_of_verts, src->xyz_coords);
    fprintf(f, " <param name=\"X\" type=\"float\" />\n");
    fprintf(f, " <param name=\"Y\" type=\"float\" />\n");
    fprintf(f, " <param name=\"Z\" type=\"float\" />\n");
    fprintf(f, " </accessor>\n");
    fprintf(f, " </technique_common>\n");
    fprintf(f, " </source>\n");

    fprintf(f, " <vertices id=\"ID%pVERTICES\">\n", mat);
    fprintf(f, " <input semantic=\"POSITION\" source=\"#ID%pSOURCE\" />\n", src->xyz_coords);
    fprintf(f, " </vertices>\n");

    fprintf(f, " <triangles count=\"%d\" material=\"Material2\">\n", mat->number_of_tris);
    fprintf(f, " <input offset=\"0\" semantic=\"VERTEX\" source=\"#ID%pVERTICES\" />\n", mat);
    fprintf(f, " <p>");

    for (j = 0; j < mat->number_of_tris; j++) {
    fprintf(f, "%d %d %d ", mat->tris[j].a, mat->tris[j].b, mat->tris[j].c);
    }

    fprintf(f, "</p>\n");
    fprintf(f, " </triangles>\n");

    fprintf(f, " </mesh>\n");
    fprintf(f, " </geometry>\n");
    }
    fprintf(f, " </library_geometries>\n");

    fprintf(f, " <library_materials>\n");
    fprintf(f, " <material id=\"ID4\" name=\"material\">\n");
    fprintf(f, " <instance_effect url=\"#ID3\" />\n");
    fprintf(f, " </material>\n");
    fprintf(f, " </library_materials>\n");

    fprintf(f, " <library_effects>\n");
    fprintf(f, " <effect id=\"ID3\">\n");
    fprintf(f, " <profile_COMMON>\n");
    fprintf(f, " <technique sid=\"COMMON\">\n");
    fprintf(f, " <lambert>\n");
    fprintf(f, " <diffuse>\n");
    fprintf(f, " <color>1.0000000 1.0000000 1.0000000 1.0000000</color>\n");
    fprintf(f, " </diffuse>\n");
    fprintf(f, " </lambert>\n");
    fprintf(f, " </technique>\n");
    fprintf(f, " </profile_COMMON>\n");
    fprintf(f, " </effect>\n");
    fprintf(f, " </library_effects>\n");

    fprintf(f, " <scene>\n");
    fprintf(f, " <instance_visual_scene url=\"#ID1VISUALSCENE\" />\n");
    fprintf(f, " </scene>\n");

    fprintf(f, "</COLLADA>\n");

    return 0;
    }

    int main()
    {
    int fd = open("/Users/fak/Desktop/Nokia3D/b.n3m", O_RDONLY);
    struct stat sb = {0};
    fstat(fd, &sb);

    void *data = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);

    struct model m;

    open_n3m (&m, data);

    FILE *out = fopen("/Users/fak/Desktop/Nokia3D/b.dae", "w");
    save_dae (&m, out);

    return 0;
    }