Created
January 21, 2012 06:55
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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