-
-
Save kenkawakenkenke/4736541 to your computer and use it in GitHub Desktop.
Java port of the N3M->DAE converter
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
import java.awt.Desktop; | |
import java.io.*; | |
import java.net.URL; | |
/** | |
* Ported from: http://techbeyond.wordpress.com/2012/02/04/nokia-3d-webgl-map-experiments/ | |
* Originally: https://gist.github.com/1651767 | |
* @author ken | |
* 13.02.08 @kenkawakenkenke | |
* | |
*/ | |
public class N3M_public { | |
static final String TILE_DOWNLOAD_URL="1.maptile.lbs.ovi.com/maptiler/v2/maptile/newest/satellite.day/"; | |
static final String URL_SUFFIX="jpg?token=fee2f2a877fd4a429f17207a57658582&app_id=nokiaMaps"; | |
static final String TEXTURE_URL="maps3d.svc.nokia.com/data4"; | |
/** | |
* Read methods | |
*/ | |
public static float getFloat(byte buf[], int offset){ | |
return Float.intBitsToFloat(getInt(buf,offset)); | |
} | |
public static double getDouble(byte buf[], int offset){ | |
return Double.longBitsToDouble(getLong(buf,offset)); | |
} | |
public static int getInt(byte buf[], int offset){ | |
return ((int)(0xff&buf[offset+0])<<0) | |
|((int)(0xff&buf[offset+1])<<8) | |
|((int)(0xff&buf[offset+2])<<16) | |
|((int)(0xff&buf[offset+3])<<24) | |
; | |
} | |
public static long getLong(byte buf[], int offset){ | |
return ((long)(0xff&buf[offset+0])<<0) | |
|((long)(0xff&buf[offset+1])<<8) | |
|((long)(0xff&buf[offset+2])<<16) | |
|((long)(0xff&buf[offset+3])<<24) | |
|((long)(0xff&buf[offset+4])<<32) | |
|((long)(0xff&buf[offset+5])<<40) | |
|((long)(0xff&buf[offset+6])<<48) | |
|((long)(0xff&buf[offset+7])<<56) | |
; | |
} | |
public static int getUnsignedShort(byte buf[], int offset){ | |
return ( | |
((int)(0xff&buf[offset+0])<<0) | |
|((int)(0xff&buf[offset+1])<<8) | |
); | |
} | |
public static boolean downloadFile(String urlStr, File f){ | |
if(!f.exists()){ | |
try{ | |
URL url=new URL(urlStr); | |
BufferedInputStream in=new BufferedInputStream(url.openStream()); | |
BufferedOutputStream out=new BufferedOutputStream(new FileOutputStream(f)); | |
byte bs[]=new byte[1024]; | |
int length; | |
while((length=in.read(bs))>0) | |
out.write(bs, 0, length); | |
in.close(); | |
out.close(); | |
return true; | |
}catch(Exception e){ | |
e.printStackTrace(); | |
} | |
} | |
return false; | |
} | |
public static class XYZ | |
{ | |
public final float x, y, z; | |
public XYZ(float x,float y, float z){ | |
this.x=x; | |
this.y=y; | |
this.z=z; | |
} | |
public static XYZ fromBytes(byte buf[], int offset){ | |
float x=getFloat(buf,offset); | |
float y=getFloat(buf,offset+4*1); | |
float z=getFloat(buf,offset+4*2); | |
return new XYZ(x,y,z); | |
} | |
public String toString(){ | |
return x+","+y+","+z; | |
} | |
public XYZ crossproduct(XYZ b) | |
{ | |
XYZ vector=new XYZ(this.y*b.z - b.y*this.z, | |
-(this.x*b.z)+(b.x*this.z), | |
(this.x*b.y) - (this.y*b.x) | |
); | |
return vector; | |
} | |
public XYZ normalize() | |
{ | |
double magnitude = Math.sqrt(x*x+y*y+z*z); | |
return new XYZ( | |
(float)(x/magnitude), | |
(float) (y/magnitude), | |
(float) (z/magnitude)); | |
} | |
public static XYZ getNormal(XYZ a,XYZ b,XYZ c) | |
{ | |
//AB vector | |
XYZ x1=new XYZ(b.x - a.x, | |
b.y - a.y, | |
b.z - a.z) ; | |
//AC vector | |
XYZ x2=new XYZ( | |
c.x - a.x, | |
c.y - a.y, | |
c.z - a.z) ; | |
return x1.crossproduct(x2).normalize(); | |
} | |
} | |
public static class UV | |
{ | |
public UV(float u,float v){ | |
this.u=u; | |
this.v=v; | |
} | |
public UV(){ | |
} | |
float u, v; | |
public static UV fromBytes(byte buf[], int offset){ | |
float u=getFloat(buf,offset); | |
float v=getFloat(buf,offset+4); | |
return new UV(u,v); | |
} | |
public String toString(){ | |
return u+","+v; | |
} | |
} | |
public static class Triangle | |
{ | |
public Triangle(int a,int b,int c){ | |
this.a=a; | |
this.b=b; | |
this.c=c; | |
} | |
public Triangle(){ | |
} | |
int a, b, c; | |
public static Triangle fromBytes(byte buf[], int offset){ | |
int a=getUnsignedShort(buf,offset); | |
int b=getUnsignedShort(buf,offset+2*1); | |
int c=getUnsignedShort(buf,offset+2*2); | |
return new Triangle(a,b,c); | |
} | |
public String toString(){ | |
return a+","+b+","+c; | |
} | |
} | |
public static class Source | |
{ | |
int number_of_verts; | |
XYZ[] xyz_coords; | |
UV[] uv_coords; | |
} | |
public static class Material | |
{ | |
int number_of_tris; | |
int source_index; | |
int bucket_levels ; | |
int bucket_count ; | |
String texture_name; | |
String texture; | |
boolean is_sat ; | |
int[] bucketOffsets ; | |
Triangle tris[]; | |
}; | |
public static class Model | |
{ | |
int bucket_levels; //32 | |
int number_of_sources; | |
int number_of_materials; | |
Source sources[]; | |
Material materials[]; | |
float center[]=new float[3] ; | |
float radius[]=new float[3] ; | |
float matrixFloat[]=new float[16] ; | |
double matrixDouble[]=new double[16] ; | |
public static byte[] readDataFromFile(File f){ | |
//read data | |
byte data[]=null; | |
try{ | |
BufferedInputStream in=(new BufferedInputStream(new FileInputStream(f))); | |
ByteArrayOutputStream out=new ByteArrayOutputStream(); | |
int length; | |
byte buf[]=new byte[1024]; | |
while((length=in.read(buf))>0){ | |
out.write(buf,0,length); | |
} | |
in.close(); | |
out.close(); | |
data=out.toByteArray(); | |
}catch(Exception e){ | |
e.printStackTrace(); | |
} | |
return data; | |
} | |
public Model(File f) throws Exception{ | |
this(readDataFromFile(f)); | |
} | |
public Model(byte data[]) throws Exception{ | |
byte magic[] = data; | |
if (magic[0] != 'N' || magic[1] != '3' || magic[2] != 'M') { | |
throw new Exception("incorrect file"); | |
} | |
int version = (int)(0xff&magic[3]); | |
boolean version2OrNewer= version>=50; | |
boolean version4OrNewer= version>=52; | |
number_of_sources = getInt(data,4*1); | |
number_of_materials = getInt(data,4*2); | |
sources = new Source[number_of_sources]; | |
materials = new Material[number_of_materials]; | |
bucket_levels = 32 ; | |
for (int i = 0; i < number_of_sources; i++) { | |
Source s = new Source(); | |
sources[i]=s; | |
int offset = i * 2 + 3; | |
int data_offset = getInt(data,4*offset); | |
s.number_of_verts = getInt(data,4*(offset+1)); | |
s.xyz_coords=new XYZ[s.number_of_verts]; | |
for(int j=0;j<s.number_of_verts;j++) | |
s.xyz_coords[j] = XYZ.fromBytes(data,data_offset+j*(4*3)); | |
s.uv_coords = new UV[s.number_of_verts]; | |
for(int j=0;j<s.number_of_verts;j++) | |
s.uv_coords[j]=UV.fromBytes(data, (data_offset+ s.number_of_verts*12) + j*(4*2)); | |
} | |
for (int i = 0; i < number_of_materials; i++) { | |
Material mat = new Material(); | |
materials[i]= mat; | |
int offset = number_of_sources * 2 + i * 4 + 3; | |
int indices_offset = getInt(data,4*offset);//header[offset]; | |
int textureNameOffset = getInt(data,4*(offset+3));//header[ offset +3 ] ; //DONT KNOW YET WHAT IT IS | |
mat.number_of_tris = getInt(data,4*(offset+1));//header[offset + 1]; | |
mat.source_index = getInt(data,4*(offset+2));//header[offset + 2]; | |
mat.tris=new Triangle[mat.number_of_tris]; | |
for(int j=0;j<mat.number_of_tris;j++) | |
mat.tris[j]=Triangle.fromBytes(data, indices_offset+ j*(2*3)); | |
if(version4OrNewer) | |
{ | |
int offset2 = indices_offset + mat.number_of_tris*6 ; | |
mat.bucket_levels = getUnsignedShort(data, offset2) ; | |
if( mat.bucket_levels < bucket_levels) | |
bucket_levels = mat.bucket_levels ; | |
mat.bucket_count = 1 << (mat.bucket_levels << 1) ; | |
mat.bucketOffsets=new int[mat.bucket_count+1]; | |
for(int j=0;j<mat.bucket_count;j++) | |
mat.bucketOffsets[j]= getUnsignedShort(data, offset2+ 2*(j+1)); | |
mat.bucketOffsets[ mat.bucket_count ] = mat.number_of_tris ; | |
} | |
else //older than version 4 pointclouds | |
{ | |
bucket_levels = 0 ; | |
mat.bucket_levels = 0 ; | |
} | |
int textureNameLength = (int)(0xff&magic[ textureNameOffset ]) ; | |
mat.texture_name=new String(magic, textureNameOffset+1, textureNameLength); | |
} | |
int center_radius_offset = getInt(data,4*(number_of_sources*2 +number_of_materials*4 +3)) ; | |
center[0] = getFloat(data, center_radius_offset+64+0); | |
center[1] = getFloat(data, center_radius_offset+64+4); | |
center[2] = getFloat(data, center_radius_offset+64+4*2); | |
radius[0] = getFloat(data, center_radius_offset+76+0); | |
radius[1] = getFloat(data, center_radius_offset+76+4); | |
radius[2] = getFloat(data, center_radius_offset+76+4*2); | |
if(version2OrNewer) | |
{ | |
for(int i=0; i<16; i++) | |
matrixDouble[ i ] = getDouble(data,center_radius_offset+88+ i*8); | |
for(int i=0; i<16; i++) | |
matrixFloat[ i ] = getFloat(data,center_radius_offset+ i*4); | |
} | |
else | |
{ | |
for(int i=0; i<16; i++) | |
matrixFloat[ i ] = getFloat(data,center_radius_offset+ i*4); | |
} | |
if (bucket_levels == 32) | |
bucket_levels = 0 ; | |
//get texture URL | |
for( int i=0; i< number_of_materials; i++) | |
{ | |
int strLength = materials[ i ].texture_name.length() ; | |
//ending in sat | |
if( strLength>3 && materials[ i ].texture_name.endsWith("sat")) | |
{ | |
materials[ i ].texture=String.format("%s%s%s", "../../tile/" , materials[ i ].texture_name , ".jpg" ) ; | |
materials[ i ].is_sat = true ; | |
} | |
else | |
{ | |
//starting with sat_ | |
//sat_15_20107_5242 | |
if( strLength>3 && materials[i].texture_name.startsWith("sat_")) | |
{ | |
String split[]=materials[i].texture_name.split("_"); | |
int tilex, tiley, zoom, twoPowerZoom ; | |
zoom=Integer.parseInt(split[1]); | |
tilex=Integer.parseInt(split[2]); | |
tiley=Integer.parseInt(split[3]); | |
twoPowerZoom=(int)(0.5+Math.pow(2.0, zoom)); | |
materials[i].texture=String.format("%s%d/%d/%d/256/%s" ,TILE_DOWNLOAD_URL, zoom, tiley, twoPowerZoom-1-tilex, URL_SUFFIX ) ; | |
materials[ i ].is_sat = true ; | |
materials[i].texture_name=String.format("%s.jpg", materials[ i ].texture_name ) ; | |
} | |
else | |
{ | |
//b0.texture = bw(b2.url_dir + bW) | |
//maps3d.svc.nokia.com/data4/13/4914/10/ | |
// for map_13_4918_1407_0.jpg | |
String split[]=materials[i].texture_name.split("_"); | |
int tilex, tiley, zoom ; | |
zoom=Integer.parseInt(split[1]); | |
tilex=Integer.parseInt(split[2]); | |
tiley=Integer.parseInt(split[3]); | |
String urlPrefix = obfuscateURL(zoom, tilex, tiley) ; | |
materials[ i ].texture=String.format("%s%s", urlPrefix, materials[ i ].texture_name ) ; | |
materials[ i ].is_sat = false ; | |
} | |
} | |
} | |
} | |
public boolean downloadTextures(File dir) | |
{ | |
for( int i=0; i< number_of_materials; i++) | |
{ | |
File outFile=new File(dir,materials[i].texture_name); | |
if(!outFile.exists()){ | |
String urlStr="http://"+materials[i].texture; | |
if(!downloadFile(urlStr, outFile)) | |
return false; | |
} | |
} | |
return true; | |
} | |
public void saveAsDAE (File f) throws FileNotFoundException | |
{ | |
PrintWriter out=new PrintWriter(f); | |
out.printf( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"); | |
out.printf( "<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">\n"); | |
out.printf( " <asset>\n"); | |
out.printf( " <contributor>\n"); | |
out.printf( " <authoring_tool>n3mtodae</authoring_tool>\n"); | |
out.printf( " </contributor>\n"); | |
out.printf( " <created>2012-01-21T04:10:34Z</created>\n"); | |
out.printf( " <modified>2012-01-21T04:10:34Z</modified>\n"); | |
out.printf( " <unit meter=\"0.0254000\" name=\"inch\" />\n"); | |
out.printf( " <up_axis>X_UP</up_axis>\n"); | |
out.printf( " </asset>\n"); | |
//IMPORT TEXTURE IMAGES | |
out.printf( " <library_images>"); | |
int i = 0; | |
for (i = 0; i < number_of_materials; i++) | |
{ | |
Material mat = materials[i]; | |
out.printf( "\n <image id=\"material%d-image\" name=\"material%d-image\">", mat.hashCode(), mat.hashCode()); | |
out.printf( "\n <init_from>%s</init_from>", mat.texture_name); | |
out.printf( "\n </image>"); | |
} | |
out.printf( "\n </library_images>\n"); | |
//IMPORT MATERIALS | |
out.printf( " <library_materials>"); | |
i = 0; | |
for (i = 0; i < number_of_materials; i++) | |
{ | |
Material mat = materials[i]; | |
out.printf( "\n <material id=\"material%dID\" name=\"material%d\">", mat.hashCode(), mat.hashCode()); | |
out.printf( "\n <instance_effect url=\"#material%d-effect\" />", mat.hashCode()); | |
out.printf( "\n </material>"); | |
} | |
out.printf( "\n </library_materials>\n"); | |
//DECLARE EFFECTS | |
out.printf( " <library_effects>\n"); | |
i = 0; | |
for (i = 0; i < number_of_materials; i++) | |
{ | |
Material mat = materials[i]; | |
out.printf( " <effect id=\"material%d-effect\" name=\"material%d-effect\">\n", mat.hashCode(), mat.hashCode()); | |
out.printf( " <profile_COMMON>\n"); | |
out.printf( " <newparam sid=\"material%d-image-surface\">\n", mat.hashCode()); | |
out.printf( " <surface type=\"2D\">\n"); | |
out.printf( " <init_from>material%d-image</init_from>\n", mat.hashCode()); | |
out.printf( " </surface>\n"); | |
out.printf( " </newparam>\n"); | |
out.printf( " <newparam sid=\"material%d-image-sampler\">\n", mat.hashCode()); | |
out.printf( " <sampler2D>\n"); | |
out.printf( " <source>material%d-image-surface</source>\n", mat.hashCode()); | |
out.printf( " </sampler2D>\n"); | |
out.printf( " </newparam>\n"); | |
out.printf( " <technique sid=\"COMMON\">\n"); | |
out.printf( " <lambert>\n"); | |
out.printf( " <emission>\n"); | |
out.printf( " <color>0.0000000 0.0000000 0.0000000 1.0000000</color>\n"); | |
out.printf( " </emission>\n"); | |
out.printf( " <ambient>\n"); | |
out.printf( " <color>0.0000000 0.0000000 0.0000000 1.0000000</color>\n"); | |
out.printf( " </ambient>\n"); | |
out.printf( " <diffuse>\n"); | |
out.printf( " <texture texture=\"material%d-image-sampler\" texcoord=\"UVSET0\"/>\n", mat.hashCode()); | |
out.printf( " </diffuse>\n"); | |
out.printf( " </lambert>\n"); | |
out.printf( " </technique>\n"); | |
out.printf( " </profile_COMMON>\n"); | |
out.printf( " </effect>\n"); | |
} | |
out.printf( " </library_effects>\n"); | |
out.printf( " <library_visual_scenes>\n"); | |
out.printf( " <visual_scene id=\"ID1VISUALSCENE\">\n"); | |
out.printf( " <node name=\"n3mtodae\">\n"); | |
i = 0; | |
for (i = 0; i < number_of_materials; i++) { | |
Material mat = materials[i]; | |
out.printf( " <instance_geometry url=\"#ID%dGEOMETRY\">\n", mat.hashCode()); | |
out.printf( " <bind_material>\n"); | |
out.printf( " <technique_common>\n"); | |
out.printf( " <instance_material symbol=\"material%d\" target=\"#material%dID\">\n", mat.hashCode(), mat.hashCode()); | |
out.printf( " <bind_vertex_input semantic=\"UVSET0\" input_semantic=\"TEXCOORD\" input_set=\"0\" />\n"); | |
out.printf( " </instance_material>\n"); | |
out.printf( " </technique_common>\n"); | |
out.printf( " </bind_material>\n"); | |
out.printf( " </instance_geometry>\n"); | |
} | |
out.printf( " </node>\n"); | |
out.printf( " </visual_scene>\n"); | |
out.printf( " </library_visual_scenes>\n"); | |
out.printf( " <library_geometries>\n"); | |
for (i = 0; i < number_of_materials; i++) { | |
Material mat = materials[i]; | |
Source src = sources[mat.source_index]; | |
out.printf( " <geometry id=\"ID%dGEOMETRY\">\n", mat.hashCode()); | |
out.printf( " <mesh>\n"); | |
//Write geometry position | |
out.printf( " <source id=\"ID%dPOSITION\">\n", src.xyz_coords.hashCode()); | |
out.printf( " <float_array id=\"ID%dPOSITION-ARRAY\" count=\"%d\">", src.xyz_coords.hashCode(), src.number_of_verts * 3); | |
int j = 0; | |
for (j = 0; j < src.number_of_verts; j++) { | |
out.printf( "%g %g %g ", src.xyz_coords[j].x, src.xyz_coords[j].y, src.xyz_coords[j].z); | |
} | |
out.printf( "</float_array>\n"); | |
out.printf( " <technique_common>\n"); | |
out.printf( " <accessor count=\"%d\" source=\"#ID%dPOSITION-ARRAY\" stride=\"3\">\n", src.number_of_verts, src.xyz_coords.hashCode()); | |
out.printf( " <param name=\"X\" type=\"float\" />\n"); | |
out.printf( " <param name=\"Y\" type=\"float\" />\n"); | |
out.printf( " <param name=\"Z\" type=\"float\" />\n"); | |
out.printf( " </accessor>\n"); | |
out.printf( " </technique_common>\n"); | |
out.printf( " </source>\n"); | |
//Write geometry normals | |
//3 normals per triangle | |
out.printf( " <source id=\"ID%dNORMALS\">\n", src.xyz_coords.hashCode()); | |
out.printf( " <float_array id=\"ID%dNORMALS-ARRAY\" count=\"%d\">", src.xyz_coords.hashCode(), mat.number_of_tris * 3); | |
j = 0; | |
for (j = 0; j < mat.number_of_tris; j++) { | |
XYZ normal = XYZ.getNormal( src.xyz_coords[ mat.tris[j].a ], src.xyz_coords[ mat.tris[j].b ], src.xyz_coords[ mat.tris[j].c ] ) ; | |
out.printf( "%g %g %g ", normal.x, normal.y, normal.z); | |
} | |
out.printf( "</float_array>\n"); | |
out.printf( " <technique_common>\n"); | |
out.printf( " <accessor count=\"%d\" source=\"#ID%dNORMALS-ARRAY\" stride=\"3\">\n", mat.number_of_tris, src.xyz_coords.hashCode()); | |
out.printf( " <param name=\"X\" type=\"float\" />\n"); | |
out.printf( " <param name=\"Y\" type=\"float\" />\n"); | |
out.printf( " <param name=\"Z\" type=\"float\" />\n"); | |
out.printf( " </accessor>\n"); | |
out.printf( " </technique_common>\n"); | |
out.printf( " </source>\n"); | |
//Write geometry UV | |
out.printf( " <source id=\"ID%dUV\">\n", src.xyz_coords.hashCode()); | |
out.printf( " <float_array id=\"ID%dUV-ARRAY\" count=\"%d\">", src.xyz_coords.hashCode(), src.number_of_verts * 2); | |
j = 0; | |
for (j = 0; j < src.number_of_verts; j++) { | |
out.printf( "%g %g ", src.uv_coords[j].u, src.uv_coords[j].v); | |
} | |
out.printf( "</float_array>\n"); | |
out.printf( " <technique_common>\n"); | |
out.printf( " <accessor count=\"%d\" source=\"#ID%dUV-ARRAY\" stride=\"2\">\n", src.number_of_verts, src.xyz_coords.hashCode()); | |
out.printf( " <param name=\"S\" type=\"float\" />\n"); | |
out.printf( " <param name=\"T\" type=\"float\" />\n"); | |
out.printf( " </accessor>\n"); | |
out.printf( " </technique_common>\n"); | |
out.printf( " </source>\n"); | |
out.printf( " <vertices id=\"ID%dVERTICES\">\n", mat.hashCode()); | |
out.printf( " <input semantic=\"POSITION\" source=\"#ID%dPOSITION\" />\n", src.xyz_coords.hashCode()); | |
out.printf( " </vertices>\n"); | |
out.printf( " <triangles count=\"%d\" material=\"material%d\">\n", mat.number_of_tris, mat.hashCode()); | |
out.printf( " <input offset=\"0\" semantic=\"VERTEX\" source=\"#ID%dVERTICES\" />\n", mat.hashCode()); | |
out.printf( " <input offset=\"1\" semantic=\"NORMAL\" source=\"#ID%dNORMALS\" />\n", mat.hashCode()); | |
out.printf( " <input offset=\"2\" set=\"0\" semantic=\"TEXCOORD\" source=\"#ID%dUV\" />\n", src.xyz_coords.hashCode()); | |
out.printf( " <p>"); | |
for (j = 0; j < mat.number_of_tris; j++) { | |
out.printf( "%d %d %d %d %d %d %d %d %d ", mat.tris[j].a, j, mat.tris[j].a, mat.tris[j].b, j, mat.tris[j].b, mat.tris[j].c, j, mat.tris[j].c); | |
} | |
out.printf( "</p>\n"); | |
out.printf( " </triangles>\n"); | |
out.printf( " </mesh>\n"); | |
out.printf( " </geometry>\n"); | |
} | |
out.printf( " </library_geometries>\n"); | |
out.printf( " <scene>\n"); | |
out.printf( " <instance_visual_scene url=\"#ID1VISUALSCENE\" />\n"); | |
out.printf( " </scene>\n"); | |
out.printf( "</COLLADA>\n"); | |
out.close(); | |
} | |
public static String obfuscateURL(int zoom, int tilex, int tiley) | |
{ | |
int bz = (int)(Math.floor(((zoom * 302 + 1000) / 1000.) )+0.5) ; | |
String bs=String.format("%s/%d", TEXTURE_URL, zoom) ; | |
//number of zeros | |
int numOfZeros = bz - (""+tilex).length(); | |
String tempx=""; | |
for(int i=0; i< numOfZeros; i++) | |
tempx+='0' ; | |
tempx+=tilex; | |
numOfZeros = bz - (""+tiley).length(); | |
String tempy=""; | |
for(int i=0; i< numOfZeros; i++) | |
tempy+="0"; | |
tempy+=tiley; | |
int bx ; | |
for (bx = 0; bx < bz - 2; bx += 2) | |
{ | |
bs+='/' ; | |
bs+=tempx.charAt(bx); | |
bs+=tempx.charAt(bx + 1); | |
bs+=tempy.charAt(bx); | |
bs+= tempy.charAt(bx + 1) ; | |
} | |
for (; bx < bz - 1; bx++) | |
{ | |
bs+='/'; | |
bs+=tempx.charAt(bx); | |
bs+=tempy.charAt(bx); | |
} | |
bs+='/'; | |
return bs ; | |
} | |
} | |
public static File getN3MFor(File baseDir,TileSpec spec){ | |
File file=new File(baseDir,spec.mapName()+".n3m"); | |
if(!file.exists()){ | |
int first= 100*((spec.y/10000)%100)+ (spec.x/10000)%100; | |
int second= 100*((spec.y/100)%100)+ (spec.x/100)%100; | |
int third= 10*((spec.y/10)%10)+ (spec.x/10)%10; | |
String urlStr="http://c.maps3d.svc.nokia.com/data4//"+spec.level+"/"+(first!=0?(String.format("%04d",first)+"/"):"")+(second!=0?(String.format("%04d",second)+"/"):"")+(third!=0?(String.format("%02d",third)+"/"):"")+"map_"+spec.level+"_"+spec.y+"_"+spec.x+".n3m"; | |
if(downloadFile(urlStr, file)) | |
return file; | |
return null; | |
} | |
return file; | |
} | |
public static File loadDAE(File baseDir, TileSpec spec) throws Exception{ | |
File dir=new File(baseDir,spec.mapName()); | |
if(!dir.exists()) | |
dir.mkdir(); | |
File f=getN3MFor(dir,spec); | |
if(f!=null){ | |
System.out.println(f); | |
Model m=new Model(f); | |
m.downloadTextures(dir); | |
File outFile=new File(dir,f.getName()+".dae"); | |
m.saveAsDAE(outFile); | |
File okFile=new File(dir,"ok"); | |
if(okFile.exists() || okFile.createNewFile()) | |
System.out.println(" -> exported to "+outFile); | |
return outFile; | |
} | |
return null; | |
} | |
public static class TileSpec{ | |
public final int level; | |
public final int x,y; | |
public static TileSpec fromMapName(String mapName){ | |
String split[]=mapName.split("_|\\."); | |
int level=Integer.parseInt(split[1]); | |
int x=Integer.parseInt(split[3]); | |
int y=Integer.parseInt(split[2]); | |
return new TileSpec(level, x, y); | |
} | |
public static TileSpec fromURLStr(String urlStr){ | |
String split[]=urlStr.split("/"); | |
return fromMapName(split[split.length-1]); | |
} | |
public TileSpec(int level, int x,int y){ | |
this.level=level; | |
this.x=x; | |
this.y=y; | |
} | |
public String toString(){ | |
return level+","+y+","+x; | |
} | |
public String mapName(){ | |
return "map_"+level+"_"+y+"_"+x; | |
} | |
} | |
public static void main(String[]args) throws Exception | |
{ | |
TileSpec spec=null; | |
{ | |
int level=19; | |
int x=261956; | |
int y=349934; | |
spec=new TileSpec(level, x, y); | |
} | |
File baseDir=new File("buildings"); | |
if(!baseDir.exists()) | |
baseDir.mkdir(); | |
File outFile=loadDAE(baseDir,spec); | |
Desktop.getDesktop().open(outFile); | |
} | |
} |
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 <io.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <windows.h> | |
#include <Share.h> | |
#include <math.h> | |
#define TILE_DOWNLOAD_URL "1.maptile.lbs.ovi.com/maptiler/v2/maptile/newest/satellite.day/" | |
#define URL_SUFFIX "jpg?token=fee2f2a877fd4a429f17207a57658582&app_id=nokiaMaps" | |
#define TEXTURE_URL "maps3d.svc.nokia.com/data4" | |
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; | |
int bucket_levels ; | |
int bucket_count ; | |
char texture_name[300] ; | |
char texture[500] ; | |
bool is_sat ; | |
unsigned short *bucketOffsets ; | |
struct triangle *tris; | |
}; | |
struct model | |
{ | |
int bucket_levels; //32 | |
int number_of_sources; | |
int number_of_materials; | |
struct source *sources; | |
struct material *materials; | |
float center[3] ; | |
float radius[3] ; | |
float matrixFloat[16] ; | |
double matrixDouble[16] ; | |
}; | |
bool version2OrNewer = false ; | |
bool version4OrNewer = false ; | |
struct xyz crossproduct(struct xyz a, struct xyz b) | |
{ | |
struct xyz vector; | |
vector.x = a.y*b.z - b.y*a.z ; //(Ay*Bz)-(By*Az); | |
vector.y = -(a.x*b.z)+(b.x*a.z) ; //-(Ax*Bz)+(Bx*Az); | |
vector.z = (a.x*b.y) - (a.y*b.x) ; //(Ax*By)-(Ay*Bx); | |
return vector; | |
} | |
struct xyz normalize(struct xyz a) | |
{ | |
struct xyz out ; | |
double magnitude = sqrt(a.x*a.x+a.y*a.y+a.z*a.z); | |
out.x = a.x/magnitude ; | |
out.y = a.y/magnitude ; | |
out.z = a.z/magnitude ; | |
return out ; | |
} | |
struct xyz getNormal(struct xyz a, struct xyz b, struct xyz c) | |
{ | |
struct xyz normal, x1, x2 ; | |
//AB vector | |
x1.x = b.x - a.x ; x1.y = b.y - a.y ; x1.z = b.z - a.z ; | |
//AC vector | |
x2.x = c.x - a.x ; x2.y = c.y - a.y ; x2.z = c.z - a.z ; | |
normal = crossproduct( x1, x2) ; | |
return normalize( normal ) ; | |
} | |
int getNumDecimalDigits(int value) | |
{ | |
char myString[50]; | |
sprintf(myString,"%d",value); | |
return strlen(myString); | |
} | |
char * obfuscateURL(int zoom, int tilex, int tiley) | |
{ | |
int bz = floor( float((zoom * 302 + 1000) / 1000) ) ; | |
char bs[500], tempx[500], tempy[500] ; | |
sprintf(bs, "%s/%d", TEXTURE_URL, zoom) ; | |
//number of zeros | |
int numOfZeros = bz - getNumDecimalDigits(tilex) ; | |
for(int i=0; i< numOfZeros; i++) | |
tempx[i] = '0' ; | |
sprintf( &tempx[numOfZeros], "%d", tilex) ; | |
numOfZeros = bz - getNumDecimalDigits(tiley) ; | |
for(int i=0; i< numOfZeros; i++) | |
tempy[i] = '0' ; | |
sprintf( &tempy[numOfZeros], "%d", tiley) ; | |
int stringLength = strlen( bs ) ; | |
int bx ; | |
for (bx = 0; bx < bz - 2; bx += 2) | |
{ | |
bs[stringLength++ ] = '/' ; | |
bs[stringLength++ ] = tempx[bx]; | |
bs[stringLength++ ] = tempx[bx + 1]; | |
bs[stringLength++ ] = tempy[bx]; | |
bs[stringLength++ ] = tempy[bx + 1] ; | |
} | |
for (; bx < bz - 1; bx++) | |
{ | |
bs[stringLength++ ] = '/'; | |
bs[stringLength++ ] = tempx[bx]; | |
bs[stringLength++ ] = tempy[bx]; | |
} | |
bs[stringLength++ ] = '/'; | |
bs[stringLength] = '\0'; | |
return bs ; | |
} | |
void parseTextureURLs( struct model *m ) | |
{ | |
for( int i=0; i< m->number_of_materials; i++) | |
{ | |
int strLength = strlen( m->materials[ i ].texture_name ) ; | |
//ending in sat | |
if( strLength>3 && m->materials[ i ].texture_name[ strLength - 3]=='s' && m->materials[ i ].texture_name[ strLength - 2]=='a' && m->materials[ i ].texture_name[ strLength - 1]=='t') | |
{ | |
sprintf( m->materials[ i ].texture, "%s%s%s", "../../tile/" , m->materials[ i ].texture_name , ".jpg" ) ; | |
m->materials[ i ].is_sat = true ; | |
} | |
else | |
{ | |
//starting with sat_ | |
//sat_15_20107_5242 | |
if( strLength>3 && m->materials[ i ].texture_name[0]=='s' && m->materials[ i ].texture_name[1]=='a' && m->materials[ i ].texture_name[ 2]=='t' && m->materials[ i ].texture_name[ 3]=='_') | |
{ | |
char temp[50] ; | |
int offset = 4 ; | |
int tilex, tiley, zoom, twoPowerZoom ; | |
int tokenIndex = strchr(&(m->materials[ i ].texture_name[offset]) , '_') - &(m->materials[ i ].texture_name[offset]) ; | |
strncpy(temp, &(m->materials[ i ].texture_name[offset]), tokenIndex); | |
temp[ tokenIndex] = '\0' ; | |
zoom = atoi(temp) ; | |
offset = offset + tokenIndex + 1 ; | |
tokenIndex = strchr(&(m->materials[ i ].texture_name[offset]) , '_') - &(m->materials[ i ].texture_name[offset]) ; | |
strncpy(temp, &(m->materials[ i ].texture_name[offset]), tokenIndex); | |
temp[ tokenIndex] = '\0' ; | |
tilex = atoi(temp) ; | |
offset = offset + tokenIndex + 1 ; | |
strncpy(temp, &(m->materials[ i ].texture_name[offset]), strLength - offset); | |
temp[ strLength - offset ] = '\0' ; | |
tiley = atoi(temp) ; | |
twoPowerZoom = pow(2.0, zoom) ; | |
sprintf( m->materials[ i ].texture, "%s%d/%d/%d/256/%s" ,TILE_DOWNLOAD_URL, zoom, tiley, twoPowerZoom-1-tilex, URL_SUFFIX ) ; | |
m->materials[ i ].is_sat = true ; | |
sprintf( m->materials[ i ].texture_name, "%s.jpg", m->materials[ i ].texture_name ) ; | |
} | |
else | |
{ | |
//b0.texture = bw(b2.url_dir + bW) | |
//maps3d.svc.nokia.com/data4/13/4914/10/ | |
// for map_13_4918_1407_0.jpg | |
char *urlPrefix ; | |
char temp[50] ; | |
int offset = 4 ; | |
int tilex, tiley, zoom, twoPowerZoom ; | |
int tokenIndex = strchr(&(m->materials[ i ].texture_name[offset]) , '_') - &(m->materials[ i ].texture_name[offset]) ; | |
strncpy(temp, &(m->materials[ i ].texture_name[offset]), tokenIndex); | |
temp[ tokenIndex] = '\0' ; | |
zoom = atoi(temp) ; | |
offset = offset + tokenIndex + 1 ; | |
tokenIndex = strchr(&(m->materials[ i ].texture_name[offset]) , '_') - &(m->materials[ i ].texture_name[offset]) ; | |
strncpy(temp, &(m->materials[ i ].texture_name[offset]), tokenIndex); | |
temp[ tokenIndex] = '\0' ; | |
tilex = atoi(temp) ; | |
offset = offset + tokenIndex + 1 ; | |
tokenIndex = strchr(&(m->materials[ i ].texture_name[offset]) , '_') - &(m->materials[ i ].texture_name[offset]) ; | |
strncpy(temp, &(m->materials[ i ].texture_name[offset]), tokenIndex); | |
temp[ tokenIndex] = '\0' ; | |
tiley = atoi(temp) ; | |
urlPrefix = obfuscateURL(zoom, tilex, tiley) ; | |
sprintf( m->materials[ i ].texture, "%s%s", urlPrefix, m->materials[ i ].texture_name ) ; | |
m->materials[ i ].is_sat = false ; | |
} | |
} | |
} | |
} | |
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]; | |
if( version >= 50 ) | |
version2OrNewer = true ; | |
if( version >= 52 ) | |
version4OrNewer = true ; | |
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 = (source *) calloc(m->number_of_sources, sizeof(struct source)); | |
m->materials = (material *) calloc(m->number_of_materials, sizeof(struct material)); | |
m->bucket_levels = 32 ; | |
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); //number_of_verts*3 | |
s->uv_coords = (struct uv*)((char*)data + data_offset + s->number_of_verts * 12); //number_of_verts*2 | |
} | |
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]; | |
int textureNameOffset = header[ offset +3 ] ; //DONT KNOW YET WHAT IT IS | |
mat->number_of_tris = header[offset + 1]; | |
mat->source_index = header[offset + 2]; | |
mat->tris = (struct triangle*)((char*)data + indices_offset); //number_of_tris *3 | |
printf("material[%d].number_of_tris: %d\n", i, mat->number_of_tris); | |
printf("material[%d].source_index: %d\n", i, mat->source_index); | |
if(version4OrNewer) | |
{ | |
int offset2 = indices_offset + mat->number_of_tris*6 ; | |
unsigned short *matrix = (unsigned short*)( (char*)data + offset2); | |
mat->bucket_levels = matrix[0] ; | |
if( mat->bucket_levels < m->bucket_levels) | |
m->bucket_levels = mat->bucket_levels ; | |
mat->bucket_count = 1 << (mat->bucket_levels << 1) ; | |
mat->bucketOffsets = (unsigned short *) calloc(mat->bucket_count + 1, sizeof(unsigned short)); | |
for( int i=0; i< mat->bucket_count; i++ ) | |
mat->bucketOffsets[ i ] = matrix[ i+1 ] ; | |
mat->bucketOffsets[ mat->bucket_count ] = mat->number_of_tris ; | |
} | |
else //older than version 4 pointclouds | |
{ | |
m->bucket_levels = 0 ; | |
mat->bucket_levels = 0 ; | |
} | |
unsigned char textureNameLength = magic[ textureNameOffset ] ; | |
for(int i=0; i< textureNameLength; i++) | |
mat->texture_name[i] = magic[ textureNameOffset +1 + i] ; | |
mat->texture_name[textureNameLength] = '\0' ; | |
} | |
int center_radius_offset = header[ m->number_of_sources*2 + m->number_of_materials*4 +3] ; | |
m->center[0] = ((float*)( (char*)data + center_radius_offset +64 ))[0] ; | |
m->center[1] = ((float*)( (char*)data + center_radius_offset +64 ))[1] ; | |
m->center[2] = ((float*)( (char*)data + center_radius_offset +64 ))[2] ; | |
m->radius[0] = ((float*)( (char*)data + center_radius_offset +76 ))[0] ; | |
m->radius[1] = ((float*)( (char*)data + center_radius_offset +76 ))[1] ; | |
m->radius[2] = ((float*)( (char*)data + center_radius_offset +76 ))[2] ; | |
if(version2OrNewer) | |
{ | |
for(int i=0; i<16; i++) | |
m->matrixDouble[ i ] = ((double*)( (char*)data + center_radius_offset +88 ))[i] ; | |
for(int i=0; i<16; i++) | |
m->matrixFloat[ i ] = ((float*)( (char*)data + center_radius_offset ))[i] ; | |
} | |
else | |
{ | |
for(int i=0; i<16; i++) | |
m->matrixFloat[ i ] = ((float*)( (char*)data + center_radius_offset ))[i] ; | |
} | |
if (m->bucket_levels == 32) | |
m->bucket_levels = 0 ; | |
return 0; | |
} | |
int save_dae (struct model *m, FILE *f) | |
{ | |
struct xyz normal ; | |
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"); | |
//IMPORT TEXTURE IMAGES | |
fprintf(f, " <library_images>"); | |
int i = 0; | |
for (i = 0; i < m->number_of_materials; i++) | |
{ | |
struct material *mat = &m->materials[i]; | |
fprintf(f, "\n <image id=\"material%p-image\" name=\"material%p-image\">", mat, mat); | |
fprintf(f, "\n <init_from>%s</init_from>", mat->texture_name); | |
fprintf(f, "\n </image>"); | |
} | |
fprintf(f, "\n </library_images>\n"); | |
//IMPORT MATERIALS | |
fprintf(f, " <library_materials>"); | |
i = 0; | |
for (i = 0; i < m->number_of_materials; i++) | |
{ | |
struct material *mat = &m->materials[i]; | |
fprintf(f, "\n <material id=\"material%pID\" name=\"material%p\">", mat, mat); | |
fprintf(f, "\n <instance_effect url=\"#material%p-effect\" />", mat); | |
fprintf(f, "\n </material>"); | |
} | |
fprintf(f, "\n </library_materials>\n"); | |
//DECLARE EFFECTS | |
fprintf(f, " <library_effects>\n"); | |
i = 0; | |
for (i = 0; i < m->number_of_materials; i++) | |
{ | |
struct material *mat = &m->materials[i]; | |
fprintf(f, " <effect id=\"material%p-effect\" name=\"material%p-effect\">\n", mat, mat); | |
fprintf(f, " <profile_COMMON>\n"); | |
fprintf(f, " <newparam sid=\"material%p-image-surface\">\n", mat); | |
fprintf(f, " <surface type=\"2D\">\n"); | |
fprintf(f, " <init_from>material%p-image</init_from>\n", mat); | |
fprintf(f, " </surface>\n"); | |
fprintf(f, " </newparam>\n"); | |
fprintf(f, " <newparam sid=\"material%p-image-sampler\">\n", mat); | |
fprintf(f, " <sampler2D>\n"); | |
fprintf(f, " <source>material%p-image-surface</source>\n", mat); | |
fprintf(f, " </sampler2D>\n"); | |
fprintf(f, " </newparam>\n"); | |
fprintf(f, " <technique sid=\"COMMON\">\n"); | |
fprintf(f, " <lambert>\n"); | |
fprintf(f, " <emission>\n"); | |
fprintf(f, " <color>0.0000000 0.0000000 0.0000000 1.0000000</color>\n"); | |
fprintf(f, " </emission>\n"); | |
fprintf(f, " <ambient>\n"); | |
fprintf(f, " <color>0.0000000 0.0000000 0.0000000 1.0000000</color>\n"); | |
fprintf(f, " </ambient>\n"); | |
fprintf(f, " <diffuse>\n"); | |
fprintf(f, " <texture texture=\"material%p-image-sampler\" texcoord=\"UVSET0\"/>\n", mat); | |
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, " <library_visual_scenes>\n"); | |
fprintf(f, " <visual_scene id=\"ID1VISUALSCENE\">\n"); | |
fprintf(f, " <node name=\"n3mtodae\">\n"); | |
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=\"material%p\" target=\"#material%pID\">\n", mat, mat); | |
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"); | |
//Write geometry position | |
fprintf(f, " <source id=\"ID%pPOSITION\">\n", src->xyz_coords); | |
fprintf(f, " <float_array id=\"ID%pPOSITION-ARRAY\" 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%pPOSITION-ARRAY\" 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"); | |
//Write geometry normals | |
//3 normals per triangle | |
fprintf(f, " <source id=\"ID%pNORMALS\">\n", src->xyz_coords); | |
fprintf(f, " <float_array id=\"ID%pNORMALS-ARRAY\" count=\"%d\">", src->xyz_coords, mat->number_of_tris * 3); | |
j = 0; | |
for (j = 0; j < mat->number_of_tris; j++) { | |
normal = getNormal( src->xyz_coords[ mat->tris[j].a ], src->xyz_coords[ mat->tris[j].b ], src->xyz_coords[ mat->tris[j].c ] ) ; | |
fprintf(f, "%g %g %g ", normal.x, normal.y, normal.z); | |
} | |
fprintf(f, "</float_array>\n"); | |
fprintf(f, " <technique_common>\n"); | |
fprintf(f, " <accessor count=\"%d\" source=\"#ID%pNORMALS-ARRAY\" stride=\"3\">\n", mat->number_of_tris, 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"); | |
//Write geometry UV | |
fprintf(f, " <source id=\"ID%pUV\">\n", src->xyz_coords); | |
fprintf(f, " <float_array id=\"ID%pUV-ARRAY\" count=\"%d\">", src->xyz_coords, src->number_of_verts * 2); | |
j = 0; | |
for (j = 0; j < src->number_of_verts; j++) { | |
fprintf(f, "%g %g ", src->uv_coords[j].u, src->uv_coords[j].v); | |
} | |
fprintf(f, "</float_array>\n"); | |
fprintf(f, " <technique_common>\n"); | |
fprintf(f, " <accessor count=\"%d\" source=\"#ID%pUV-ARRAY\" stride=\"2\">\n", src->number_of_verts, src->xyz_coords); | |
fprintf(f, " <param name=\"S\" type=\"float\" />\n"); | |
fprintf(f, " <param name=\"T\" 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%pPOSITION\" />\n", src->xyz_coords); | |
fprintf(f, " </vertices>\n"); | |
fprintf(f, " <triangles count=\"%d\" material=\"material%p\">\n", mat->number_of_tris, mat); | |
fprintf(f, " <input offset=\"0\" semantic=\"VERTEX\" source=\"#ID%pVERTICES\" />\n", mat); | |
fprintf(f, " <input offset=\"1\" semantic=\"NORMAL\" source=\"#ID%pNORMALS\" />\n", mat); | |
fprintf(f, " <input offset=\"2\" set=\"0\" semantic=\"TEXCOORD\" source=\"#ID%pUV\" />\n", src->xyz_coords); | |
fprintf(f, " <p>"); | |
for (j = 0; j < mat->number_of_tris; j++) { | |
fprintf(f, "%d %d %d %d %d %d %d %d %d ", mat->tris[j].a, j, mat->tris[j].a, mat->tris[j].b, j, mat->tris[j].b, mat->tris[j].c, j, 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, " <scene>\n"); | |
fprintf(f, " <instance_visual_scene url=\"#ID1VISUALSCENE\" />\n"); | |
fprintf(f, " </scene>\n"); | |
fprintf(f, "</COLLADA>\n"); | |
return 0; | |
} | |
void downloadTextures( model *m ) | |
{ | |
char cmd[600] ; | |
for( int i=0; i< m->number_of_materials; i++) | |
{ | |
sprintf( cmd, "C:\\wget\\wget.exe -O %s http://%s", m->materials[i].texture_name, m->materials[i].texture ) ; | |
system(cmd) ; | |
} | |
} | |
int main() | |
{ | |
//int fd ; //= open("/Users/fak/Desktop/Nokia3D/b.n3m", O_RDONLY); | |
//_sopen_s( &fd, "f_stat.out", O_RDONLY) ; | |
int fd = _sopen("C:/maps3D/map_19_327120_154308.n3m", O_RDONLY, _SH_DENYNO); | |
struct stat sb = {0}; | |
fstat(fd, &sb); | |
//void *data = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); | |
HANDLE fm; | |
HANDLE h = (HANDLE) _get_osfhandle (fd); | |
fm = CreateFileMapping( h, NULL, PAGE_READONLY, 0,0, NULL); | |
void *data = static_cast<void*>(MapViewOfFile( fm, FILE_MAP_READ, 0, 0, sb.st_size)); | |
struct model m; | |
open_n3m (&m, data); | |
parseTextureURLs( &m ) ; | |
downloadTextures( &m ) ; | |
FILE *out = fopen("C:/maps3D/map_19_327120_154308.dae", "w"); | |
save_dae (&m, out); | |
UnmapViewOfFile(data); | |
CloseHandle(fm); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note to others in the future: Some errors may be caused by the
Desktop.getDesktop()
line. Comment it out if it gives you trouble!(Still trying to figure out the mapping system for x and y to coordinates though!)