Package com.l2client.app

Source Code of com.l2client.app.NavConverter

package com.l2client.app;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.PrintWriter;
import java.nio.FloatBuffer;
import java.util.Locale;

import com.jme3.asset.AssetManager;
import com.jme3.asset.DesktopAssetManager;
import com.jme3.export.binary.BinaryExporter;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.mesh.IndexBuffer;
import com.jme3.system.NanoTimer;
import com.jme3.system.Timer;
import com.l2client.asset.FullPathFileLocator;
import com.l2client.navigation.TiledNavMesh;

/**
* converts all .obj files in a directory
* into a tiled navmesh (.jnv) the name of the .obj file must conform to x_y.obj
* naming convention where x and y are the tile numbers in x, y direction l2j's
* center is in x between region 19 (-32768) and 20 (+32768) and in y between
* region 18 (+32768) and 17 (-32768) so the upper left corner in 0/0 world
* coordinates is on tile 160, 144 regions are divided into 8x8 tiles so 20*8 is
* 160 for the 0 tile with the 0 x coordinate
*/
public class NavConverter {
 
  private static String fileEnding = "nav.obj";

  private static AssetManager assetMan = new DesktopAssetManager(Thread
      .currentThread().getContextClassLoader()
      .getResource("com/l2client/asset/loader.cfg"));

  private static FilenameFilter navFileFilter = new FilenameFilter() {

    @Override
    public boolean accept(File dir, String name) {
      if (name.endsWith(fileEnding)) {
//        String[] xy = name.substring(0, name.length()-fileEnding.length()).split("_");
//        if (xy.length != 2) {
//          System.out.println("File " + name
//              + " does not conform to x_y"+fileEnding+" file name convention");
//          return false;
//        }
       
//          try {
//            int i = Integer.parseInt(xy[0]);
//            i = Integer.parseInt(xy[1]);
//          } catch (NumberFormatException e) {
//            System.out.println("File " + name
//                + " does not conform to x_y"+fileEnding+" file name convention");
//          }
        return true;
      }

      return false;
    }
  };
 
  public NavConverter(){
  }


  /**
   * @param args
   *            directory of the exported files, TODO flags vsam for only
   *            converting meshes, skeletons, anims, materials
   * @throws Throwable
   */
  public static void main(String[] args) throws Throwable {
    if (args != null && args.length != 1) {
      System.out
          .println("ERROR: compiler needs a directory or file to start converting "+fileEnding+" files");
      // return -10;
      return;
    }

    File file = new File(args[0]);
   
    assetMan.registerLocator(file.toString(), FullPathFileLocator.class);

    if (!file.isDirectory()) {
      if(navFileFilter.accept(file.getParentFile(), file.getName())){
        NavConverter3 com = new NavConverter3();
        com.convertNav(file);
      } else {
        System.out.println("ERROR: compiler needs a directory or file for files to convert from");
        return;// -20;
      }
    } else {
      NavConverter com = new NavConverter();
//      com.setMeshRelative(false);
      com.convert(file);
    }
  }

  /**
   * should be true if your model is located at 0/0 and must be moved to its
   * offset false if your model is already in/at world coordinates
   */
  private boolean isMeshRelative = true;

  /**
   * @param isMeshRelative
   *            the isMeshRelative to set
   */
  public void setMeshRelative(boolean isMeshRelative) {
    this.isMeshRelative = isMeshRelative;
  }

  private void convert(File directory) throws Throwable {
    for (File ff : directory.listFiles(navFileFilter))
      convertNav(ff);

    for (File fs : directory.listFiles())
      if (fs.isDirectory())
        convert(fs);
  }

  public int convertNav(File from) throws Throwable {
    Timer t = new NanoTimer();
    float time = 0f;

    // new loader each time, yes
    try {
      Geometry g;
      // need to load vial loadModel, JME does not see obj, etc as
      // Assets..
      t.reset();
      Spatial n = (Spatial) assetMan.loadModel(from.getAbsolutePath());
      time = t.getTimeInSeconds();
      System.out.println("File " + from.getAbsolutePath() + " loaded in "
          + time + " seconds");
      if (n instanceof Geometry) {
        g = (Geometry) n;
        n = new Node(g.getName());
        ((Node)n).attachChild(g);
      } else if (n instanceof Node) {
        if (((Node) n).getChildren().size() > 1)
          throw new Throwable(
              "Mesh with more children detected than one on "
                  + from.getName());
        g = (Geometry) ((Node) n).getChild(0);
      } else
        throw new Throwable("Spatial loaded was unexpected type "
            + n.getClass());
      // jme fucked up the model names, and ignores any object name
      // entries so we fix a bit
      String fName = from.getName().substring(0,
          from.getName().length() - fileEnding.length());// without .nav
      g.setName(fName.toLowerCase());
      TiledNavMesh navMesh = new TiledNavMesh();

      {
      String[] xy = from.getParentFile().getName().split("_");
      // l2j's center is in x between region 19 (-32768) and 20 (+32768)
      // and in y between region 18 (+32768) and 17 (-32768)
     
      // minus 20*2048, 20 because region count starts with 0_0,
      // 2048 because one region consists of 8x8 tiles (each 256x256 long)
      int xd = (Integer.parseInt(xy[0]) * 256) - (20 * 2048);
      // minus 18*2048
      int yd = (Integer.parseInt(xy[1])) * 256 - (18 * 2048);
     
      // center is in top left corner for nav mesh to be consistent with
      // this for borders move x right, move y up by half size
      Vector3f offset = new Vector3f(xd + 128, 0, yd - 128);
      System.out.println("Offset for "+from.getParentFile().getName()+"/nav2.obj should be at:"+offset);
      }
     
      navMesh.loadFromMesh(g.getMesh(), Vector3f.ZERO, isMeshRelative);
     
      time = t.getTimeInSeconds();
      System.out.println("File " + from.getAbsolutePath()
          + " converted in " + time + " seconds");
      String path = from.getAbsolutePath();
      String parent = from.getParent();
      // replace .nav with .jnv
      t.reset();
      BinaryExporter.getInstance().save(navMesh,
          new File(parent+"/nav.jnv"));
      time = t.getTimeInSeconds();
//      System.out.println("File "+parent+"/nav.jnv saved in "
//          + time + " seconds");
//      t.reset();
//      writeMeshToObjFile(mesh,
//          new File(parent+"/nav.obj"));
//      time = t.getTimeInSeconds();
//      System.out.println("File "+parent+"/nav.obj saved in "
//          + time + " seconds");
      n = null;
      navMesh = null;
      System.out.println("-------------------------------------------------------");
    } catch (Exception e) {
      System.out.println("Failed to create mesh from File "+from);
      e.printStackTrace();
      System.out.println("-------------------------------------------------------");
      return -300;
    }
    return 0;
  }


  private void writeMeshToObjFile(Mesh mesh, File file) {
    try {
      PrintWriter p = new PrintWriter(file);
      p.printf(Locale.ENGLISH,"#verts\n");
      //verts
      FloatBuffer bu = mesh.getFloatBuffer(Type.Position);
      bu.rewind();
      for(int i=0; i<bu.capacity(); i+=3) {
        p.printf(Locale.ENGLISH,"v %.4f %.4f %.4f\n", bu.get(), bu.get(), bu.get());
      }
      // tex
      bu = mesh.getFloatBuffer(Type.TexCoord);
      if(bu != null) {
        bu.rewind();
        for(int i=0; i<bu.capacity(); i+=3) {
          p.printf(Locale.ENGLISH,"vt %.4f %.4f %.4f\n", bu.get(), bu.get(), bu.get());
        }
      }
      // norm
      bu = mesh.getFloatBuffer(Type.Normal);
      if(bu != null) {
        bu.rewind();
        for(int i=0; i<bu.capacity(); i+=3) {
          p.printf(Locale.ENGLISH,"vn %.4f %.4f %.4f\n", bu.get(), bu.get(), bu.get());
        }
      }
      //indices
      IndexBuffer ib = mesh.getIndexBuffer();
      if(ib != null){
        p.printf(Locale.ENGLISH,"#faces\n");
        switch(mesh.getMode()){
        case Triangles: writeTriangleBuffer(ib,p); break;
        case TriangleStrip:  writeTriangleStripBuffer(ib,p); break;
//        case TriangleFan:  writeTriangleFanBuffer(ib,p);break;
        default: throw new RuntimeException("Mesh mode not supported:"+mesh.getMode());
        }
      }
      p.flush();     
      p.close();
    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }


  private void writeTriangleStripBuffer(IndexBuffer ib, PrintWriter p) {
    int x = ib.get(0)+1;
    int y = ib.get(1)+1;
    int z = ib.get(2)+1;
    p.printf("f %d %d %d\n", x, y, z);
    for(int i=3; i<ib.size();i++) {
      x=y;y=z;z=ib.get(i)+1;
      p.printf("f %d %d %d\n", x, y, z);
    }
  }


  private void writeTriangleBuffer(IndexBuffer ib, PrintWriter p) {
    for(int i=0; i<ib.size();i+=3) {
      p.printf("f %d %d %d\n", ib.get(i)+1, ib.get(i+1)+1, ib.get(i+2)+1);
    }
  }
}
TOP

Related Classes of com.l2client.app.NavConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.