Skip to content

Instantly share code, notes, and snippets.

@praeclarum
Created January 21, 2012 06:55
Show Gist options
  • Save praeclarum/1651767 to your computer and use it in GitHub Desktop.
Save praeclarum/1651767 to your computer and use it in GitHub Desktop.
Converts Nokia 3D models to DAE models (http://maps3d.svc.nokia.com/webgl/index.html)
#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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment