LWO & HPS asset loaders

HPS models are MetaVR models. Old format, typically used in Stealth viewers for simulations. LWO is still around and I still import models for it, so I’m including it as well. Created both loaders in jME 1.0 a few years ago and ported them to jME3.





LWOLoader.java

[java]

package com.jme3.scene.plugins;



import java.io.ByteArrayInputStream;

import java.io.DataInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.nio.FloatBuffer;

import java.nio.IntBuffer;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.LinkedList;

import java.util.List;

import java.util.Map;

import java.util.logging.Level;

import java.util.logging.Logger;



import com.jme3.asset.AssetInfo;

import com.jme3.asset.AssetLoader;

import com.jme3.asset.AssetManager;

import com.jme3.export.binary.BinaryExporter;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Mesh;

import com.jme3.scene.Node;

import com.jme3.scene.VertexBuffer.Type;

import com.jme3.shader.VarType;

import com.jme3.util.BufferUtils;



public class LWOLoader implements AssetLoader {

private static Logger logger = Logger.getLogger(“LWOLoader”);



/**

  • Creates a node from a .lwo InputStream and then writes that node to the given
  • OutputStream in jME’s binary format
  • @param LWOStream An InputStream pointing to the .lwo file
  • @param o The stream to write it’s binary equivalent to
  • @throws java.io.IOException If anything funky goes wrong with reading information

    /

    public void convert(InputStream LWOStream,OutputStream o, AssetManager assetManager) throws IOException {

    if (LWOStream==null)

    throw new NullPointerException(“Unable to load null streams”);

    Node newnode=new Node(“lwo model”);

    new LWOLoader.LWOLoaderCopy(LWOStream,newnode, assetManager);

    BinaryExporter.getInstance().save(newnode,o);

    }



    private static class LWOLoaderCopy {

    private static final long serialVersionUID = 1L;

    private Node mynode;

    private DataInputStream reader;

    private char[] idTag = new char[4];

    private Vector3f[] points = null;

    private String[] surfaces = null;

    private List<Surface> surfaceList = new ArrayList<Surface>();

    private Map<Integer,List<int[]>> polyMap;

    private AssetManager assetManager;



    public LWOLoaderCopy(InputStream LWOStream,Node node, AssetManager assetManager) throws IOException {

    this.mynode=node;

    this.assetManager = assetManager;

    load(LWOStream);

    }



    public void load(InputStream is) throws IOException {

    if (null == is) {

    logger.log(Level.SEVERE,“Null URL could not load LWO.”);

    return;

    }



    try {

    is.available();



    reader = new DataInputStream(is);

    readIdTag(reader,idTag);



    if (!String.valueOf(idTag).equals(“FORM”)) {

    throw new IOException(“Unable to read IFF file header, found '”+String.valueOf(idTag)+"’");

    }



    int size = reader.readInt();

    byte[] form = new byte[size];



    reader.readFully(form);

    reader.close();



    reader = new DataInputStream(new ByteArrayInputStream(form));

    readIdTag(reader,idTag);



    if (!String.valueOf(idTag).equals(“LWOB”)) {

    throw new IOException(“File is not LWOB object”);

    }



    byte[] chunk;

    String chunkName;

    while(reader.available() > 0) {

    readIdTag(reader,idTag);



    chunkName = String.valueOf(idTag);



    size = reader.readInt();

    chunk = new byte[size];

    reader.readFully(chunk);

    if (chunkName.equals(“PNTS”)) {

    points = readPoints(chunk);

    }

    else if (chunkName.equals(“SRFS”)) {

    surfaces = readSurfaces(chunk);

    }

    else if (chunkName.equals(“SURF”)) {

    Surface newSurf = readSurf(chunk);

    if (newSurf != null)

    surfaceList.add(newSurf);

    }

    else if (chunkName.equals(“POLS”)) {

    polyMap = readPolys(chunk);

    }

    else {

    System.out.println(" chunk: "+chunkName+ " bytes: "+size);

    }

    }



    } catch (IOException e) {

    logger.log(Level.SEVERE,"Could not load " + is.toString(),e);

    e.printStackTrace();

    }



    if (points == null || points.length==0) {

    throw new IOException(“No points found”);

    }



    if (surfaces == null || surfaces.length==0) {

    throw new IOException(“No surfaces found”);

    }



    if (surfaceList.isEmpty()) {

    throw new IOException(“No surface descriptions found”);

    }



    if (polyMap.isEmpty()) {

    throw new IOException(“No polys found”);

    }



    Map<String,Surface> surfaceMap = new HashMap<String,Surface>();

    for (Surface surface : surfaceList) {

    surfaceMap.put(surface.surfaceName,surface);

    }



    FloatBuffer vertBuffer = BufferUtils.createFloatBuffer(points);

    for (int i = 0 ; i < surfaces.length; i++) {

    Mesh mesh = new Mesh();

    Geometry geometry = new Geometry(surfaces,mesh);



    int triangleCount = 0;

    List<int[]> polys = polyMap.get(i+1);

    for (int[] poly : polys) triangleCount+= poly.length-2;

    IntBuffer indexBuffer = BufferUtils.createIntBuffer(triangleCount
    3);



    mesh.setBuffer(Type.Position, 3, vertBuffer);

    mesh.setBuffer(Type.Index, 3, indexBuffer);



    for (int[] poly : polys) {

    for (int j=2;j<poly.length;j++) {

    indexBuffer.put(poly[0]).put(poly[j-1]).put(poly[j]);

    }

    }



    Surface surface = surfaceMap.get(surfaces);

    if (surface.diffuse != null || surface.specular != null || surface.color != null) {

    Material ms = new Material(assetManager,“Common/MatDefs/Light/Lighting.j3md”);

    geometry.setMaterial(ms);



    if (surface.diffuse != null) {

    ms.setColor(“m_Diffuse”, surface.diffuse);

    }

    if (surface.specular != null) {

    ms.setColor(“m_Specular”, surface.specular);

    }

    if (surface.color != null) {

    ms.setColor(“m_Ambient”, surface.color);

    }

    if (surface.glossy>0.0f) {

    ms.setParam(“m_Shininess”, VarType.Float,surface.glossy128);

    }

    ms.setBoolean(“m_UseMaterialColors”, true);

    }

    mynode.attachChild(geometry);

    }

    }



    private static void readIdTag(DataInputStream dis, char[] idTag) throws IOException {

    idTag[0] = (char)dis.readByte();

    idTag[1] = (char)dis.readByte();

    idTag[2] = (char)dis.readByte();

    idTag[3] = (char)dis.readByte();

    }



    private static Vector3f[] readPoints(byte[] chunk) throws IOException {

    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(chunk));

    int numPoints = chunk.length/12;

    Vector3f[] points = new Vector3f[numPoints];

    for (int i = 0; i<numPoints; i++) {

    points = new Vector3f(dis.readFloat(),dis.readFloat(),dis.readFloat());

    }

    dis.close();

    return points;

    }



    private static String[] readSurfaces(byte[] chunk) throws IOException {

    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(chunk));

    LinkedList<String> surfaces = new LinkedList<String>();

    String surfaceName;

    while (dis.available()>0) {

    surfaceName = readString(dis);

    surfaces.addLast(surfaceName);

    }

    dis.close();

    return surfaces.toArray(new String[0]);

    }



    private static String readString(DataInputStream dis) throws IOException {

    int index = 0;

    char[] string = new char[256];

    string[index] = (char)dis.readByte();

    while (string[index] != 0) {

    index++;

    string[index] = (char)dis.readByte();

    }



    dis.mark(2);

    if (dis.available()>0 && dis.readByte() != 0) dis.reset();



    return String.valueOf(string).substring(0, index);

    }



    private static Map<Integer,List<int[]>> readPolys(byte[] chunk) throws IOException {

    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(chunk));

    Map<Integer,List<int[]>> polyMap = new HashMap<Integer,List<int[]>>();



    int size;

    int surface;

    List<int[]> list = null;

    while (dis.available()>0) {

    size = dis.readUnsignedShort();

    int[] poly = new int[size];

    for (int i=0;i<size;i++) {

    poly = dis.readUnsignedShort();

    }

    surface = dis.readUnsignedShort();



    list = polyMap.get(surface);

    if (list == null) {

    list = new ArrayList<int[]>();

    polyMap.put(surface, list);

    }

    list.add(poly);

    }

    dis.close();



    return polyMap;

    }



    private static Surface readSurf(byte[] chunk) throws IOException {

    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(chunk));

    Map<Integer,List<int[]>> polyMap = new HashMap<Integer,List<int[]>>();



    int size;

    char[] idTag = new char[4];

    String chunkName;

    String surfName = readString(dis);



    Surface surface = new Surface();

    surface.surfaceName = surfName;



    while (dis.available()>0) {

    readIdTag(dis,idTag);



    chunkName = String.valueOf(idTag);



    size = dis.readUnsignedShort();

    if (chunkName.equals(“COLR”)) {

    surface.color = new ColorRGBA(1,1,1,1);

    surface.color.r = ((float)dis.readByte())/255f;

    surface.color.g = ((float)dis.readByte())/255f;

    surface.color.b = ((float)dis.readByte())/255f;

    dis.readByte();

    }

    else if (chunkName.equals(“FLAG”)) {

    surface.flags = dis.readShort();

    }

    else if (chunkName.equals(“DIFF”)) {

    surface.diffuse = surface.color.clone();

    surface.diffuse.a = ((float)dis.readUnsignedShort())/256f;

    }

    else if (chunkName.equals(“SPEC”)) {

    surface.specular = surface.color.clone();

    surface.specular.a = ((float)dis.readUnsignedShort())/256f;

    }

    else if (chunkName.equals(“GLOS”)) {

    surface.glossy = ((float)dis.readUnsignedShort())/256f;

    }

    else if (chunkName.equals(“TRAN”)) {

    surface.alpha = ((float)dis.readUnsignedShort())/256f;

    }

    else if (chunkName.equals(“VDIF”)) {

    surface.diffuse = surface.color.clone();

    surface.diffuse.a = dis.readFloat();

    }

    else if (chunkName.equals(“VTRN”)) {

    surface.alpha=dis.readFloat();

    }

    else if (chunkName.equals(“VSPC”)) {

    surface.specular = surface.color.clone();

    surface.specular.a = dis.readFloat();

    }

    else if (chunkName.equals(“TFLG”)) {

    surface.textureFlags = dis.readUnsignedShort();

    }

    else if (chunkName.equals(“REFL”)) {

    surface.reflective = ((float)dis.readUnsignedShort())/256f;

    }

    else if (chunkName.equals(“TAAS”)) {

    surface.textureAntiAliasing = dis.readFloat();

    }

    else if (chunkName.equals(“TSIZ”)) {

    surface.textureSize = new Vector3f();

    surface.textureSize.x = dis.readFloat();

    surface.textureSize.y = dis.readFloat();

    surface.textureSize.z = dis.readFloat();

    }

    else if (chunkName.equals(“TIMG”)) {

    surface.textureImage = readString(dis);

    }

    else if (chunkName.equals(“TALP”)) {

    surface.textureAlphaImage = readString(dis);

    }

    else if (chunkName.equals(“TCTR”)) {

    surface.textureCenter = new Vector3f();

    surface.textureCenter.x = dis.readFloat();

    surface.textureCenter.y = dis.readFloat();

    surface.textureCenter.z = dis.readFloat();

    }

    else if (chunkName.equals(“TWRP”)) {

    surface.textureWrapS = dis.readUnsignedShort();

    surface.textureWrapT = dis.readUnsignedShort();

    }

    else if (chunkName.equals(“BTEX”)) {

    String tex = readString(dis);

    surface.BTEX=tex;

    }

    else if (chunkName.equals(“CTEX”)) {

    String tex = readString(dis);

    surface.CTEX=tex;

    }

    else if (chunkName.equals(“DTEX”)) {

    String tex = readString(dis);

    surface.DTEX=tex;

    }

    else if (chunkName.equals(“LTEX”)) {

    String tex = readString(dis);

    surface.LTEX=tex;

    }

    else if (chunkName.equals(“RTEX”)) {

    String tex = readString(dis);

    surface.RTEX=tex;

    }

    else if (chunkName.equals(“STEX”)) {

    String tex = readString(dis);

    surface.STEX=tex;

    }

    else if (chunkName.equals(“TTEX”)) {

    String tex = readString(dis);

    surface.TTEX=tex;

    }

    else if (chunkName.equals(“SMAN”)) { //smoothing angle

    float val = dis.readFloat();

    }

    else if (chunkName.equals(“RIND”)) {

    float val = dis.readFloat();

    }

    else {

    byte[] subChunk = new byte[size];

    dis.readFully(subChunk);

    subChunk = null;

    }

    }

    dis.close();

    return surface;

    }

    }

    /


    434f4c52 0004 COLR { base color is yellow

    f0 b4 00 00 240, 180, 0

    464c4147 0002 FLAG { surface is double-sided

    0100 [00100000000]

    44494646 0002 DIFF { fixed 60% diffuse

    009a 154

    53504543 0002 SPEC { fixed 80% specular

    00cd 205

    474c4f53 0002 GLOS { “High” glossiness

    0100 256

    5245464c 0002 REFL { fixed 20% reflective

    0033 51

    5452414e 0002 TRAN { fixed 40% transparent

    0066 102

    54464c47 0002 TFLG { Y-axis; world-coords;

    006a [1101010] pixel blending; antialiasing

    54414153 0004 TAAS { texture antializing strength

    3f800000 1.0 100%

    54414d50 0004 TAMP { bump amplitude

    3f000000 1.5 150%

    54495030 0002 TIP0 { first integer parameter

    0003 3 3 fractal noise frequences



    CTEX, DTEX, STEX, RTEX, TTEX, LTEX, BTEX (color, diffuse, spec, reflective, texture, luminosity, bump texture)

    /

    private static class Surface {

    String surfaceName;

    int flags;

    ColorRGBA diffuse = null;

    ColorRGBA specular = null;

    ColorRGBA color = null;

    float reflective;

    float glossy;

    float alpha;

    String textureImage = null;

    String textureAlphaImage = null;

    int textureFlags;

    float textureAntiAliasing;

    int textureWrapS, textureWrapT;

    Vector3f textureCenter = null;

    Vector3f textureSize = null;

    String CTEX, DTEX, STEX, RTEX, TTEX, LTEX, BTEX;



    public String toString() {

    return

    " Name: "+surfaceName+

    "n Flags: "+Integer.toBinaryString(flags)+

    "n Diffuse: "+diffuse+

    "n Specular: "+specular+

    "n Color: "+color+

    "n Reflective: "+reflective+

    "n Glossy: "+glossy+

    "n Alpha: "+alpha+

    "n Texture: "+textureImage+

    "n Tex-Alpha: "+textureAlphaImage+

    "n Tex-AA: "+textureAntiAliasing+

    "n Tex-Flags: "+Integer.toBinaryString(textureFlags)+

    "n Tex-WrapS: "+textureWrapS+

    "n Tex-WrapT: "+textureWrapT+

    "n Tex-Center: "+textureCenter+

    "n Tex-Size: "+textureSize+

    "n CTEX: "+CTEX+

    "n DTEX: "+DTEX+

    "n STEX: "+STEX+

    "n RTEX: "+RTEX+

    "n TTEX: "+TTEX+

    "n LTEX: "+LTEX+

    "n BTEX: "+BTEX

    ;



    }

    }

    @Override

    public Object load(AssetInfo assetInfo) throws IOException {

    Node newnode=new Node(“lwo model”);

    new LWOLoader.LWOLoaderCopy(assetInfo.openStream(),newnode,assetInfo.getManager());

    return newnode;

    }

    }

    [/java]



    HPSLoader.java

    [java]

    package com.jme3.scene.plugins;



    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.nio.FloatBuffer;

    import java.nio.IntBuffer;

    import java.util.ArrayList;

    import java.util.HashMap;

    import java.util.Iterator;

    import java.util.List;

    import java.util.Map;

    import java.util.logging.Level;

    import java.util.logging.Logger;



    import com.jme3.asset.AssetInfo;

    import com.jme3.asset.AssetKey;

    import com.jme3.asset.AssetLoader;

    import com.jme3.asset.AssetManager;

    import com.jme3.asset.ModelKey;

    import com.jme3.material.Material;

    import com.jme3.scene.Geometry;

    import com.jme3.scene.Mesh;

    import com.jme3.scene.Node;

    import com.jme3.scene.VertexBuffer.Type;

    import com.jme3.texture.Texture;

    import com.jme3.util.BufferUtils;



    public class HPSLoader implements AssetLoader {

    /
    * Reference to the OneSAFLogger object. */

    private static Logger logger = Logger.getLogger(“HPSLoader”);



    public static class LODNode {

    public double minRange, maxRange;

    List<ModelData> modelData = new ArrayList<ModelData>();

    public String toString() {

    return “BD[” + minRange + “…” + maxRange + “] " + modelData.size() + " model data elements”;

    }

    }



    public static class ModelData {

    public VertexData vertexData = new VertexData();

    public List<TriData> triData = new ArrayList<TriData>();

    }



    public static class VertexData {

    public int vertices;

    public FloatBuffer vertexBuffer;

    public FloatBuffer normalBuffer;

    public FloatBuffer textureBuffer;

    }



    public static class TriData {

    public int triangles;

    public int textureNumber;

    public IntBuffer indicesBuffer;

    }



    public static class HPSModel {

    private LODNode[] modelData;

    public int numTextures;

    public Material[] textures;

    int currentLineNumber = 0;

    private AssetManager assetManager = null;

    private ModelKey key = null;



    /**
  • Format can contain sections of:
  • Switch
  • Parent
  • RotatingAnimation
  • Geometry (*) – we handle this
  • Subface
  • LOD (*) – we handle this

    *

    */

    public HPSModel(AssetInfo info) throws IOException {

    key = (ModelKey) info.getKey();

    assetManager = info.getManager();

    BufferedReader reader = new BufferedReader(new InputStreamReader(info.openStream()));

    readHeader(reader);

    String line = reader.readLine();

    currentLineNumber++;

    List<LODNode> lodNodes = new ArrayList<LODNode>();

    LODNode lodNode = new LODNode();

    lodNode.minRange = lodNode.maxRange = -1.0;

    lodNodes.add(lodNode);

    List<ModelData> lodModelData = lodNode.modelData;



    while (line!=null) {

    if (line.startsWith("LOD")) {

    double minDistance = 0.0, maxDistance = 0.0;

    String[] data = line.split(" ");

    try {

    minDistance = Double.valueOf(data[2]);

    maxDistance = Double.valueOf(data[3]);

    }

    catch (Exception e) {

    logger.log(Level.SEVERE,"unable to parse LOD info line#"
  • currentLineNumber + ":" + line);

    }

    lodNode = getLODNode(minDistance, maxDistance, lodNodes);

    lodModelData = lodNode.modelData;

    }

    else if (line.startsWith("Geometry")) {

    try {

    readGeometry(line, reader, lodModelData);

    }

    catch (Exception e) {

    logger.log(Level.SEVERE,"error on/after line#" + currentLineNumber,e);

    }



    }

    line = reader.readLine();

    currentLineNumber++;

    }

    LODNode defaultLOD = (LODNode)lodNodes.get(0);

    if (defaultLOD.modelData.isEmpty()) {

    lodNodes.remove(0);

    }



    modelData = (LODNode[])lodNodes.toArray(new LODNode[0]);

    }



    LODNode getLODNode(double minRange, double maxRange, List<LODNode> lodNodes) {

    LODNode found = null;

    for(Iterator<LODNode> i=lodNodes.iterator();i.hasNext() && found == null;) {

    LODNode lodEntry = i.next();

    if ((StrictMath.abs(minRange - lodEntry.minRange) < 1.0e-10

    && StrictMath.abs(maxRange - lodEntry.maxRange) < 1.0e-10)) {

    found = lodEntry;

    }



    }

    if (found == null) {

    found = new LODNode();

    found.minRange = minRange;

    found.maxRange = maxRange;

    lodNodes.add(found);

    }

    return found;

    }



    public List<ModelData> getModelData() {

    return getModelData(-1.0);

    }



    public List<ModelData> getModelData(double range) {

    /*

    logger.info("model LOD bins:");

    for(int i=0;i<modelData.length;i++) {

    logger.info(modelData);

    }

    */

    for(int i=0;i<modelData.length;i++) {

    if (modelData.minRange-1.0 < range

    && modelData.maxRange+1.0 > range) {

    // logger.info("using LOD modelData:" + modelData);

    return modelData.modelData;

    }

    }

    return modelData[0].modelData;

    }





    private void readHeader(BufferedReader reader) throws IOException {

    String line = reader.readLine();

    currentLineNumber++;

    String[] args= line.split("\s");

    numTextures = Integer.parseInt(args[0]);

    String textureName;

    textures = new Material[numTextures];

    for (int i=0;i<numTextures;i++) {

    String[] lineargs = reader.readLine().split("\s");

    textureName=lineargs[0];

    currentLineNumber++;

    String useName = findFileMatch(key.getFolder(), textureName, assetManager);

    if (useName == null) {

    logger.log(Level.SEVERE,"unable to find texture [" + textureName
  • "] used by model:" + key);

    }

    else {

    Texture texture = assetManager.loadTexture(useName);

    if (texture == null) {

    logger.log(Level.SEVERE,"error loading texture [" + useName
  • "] used by model:" + key);

    }

    else {

    Material mat = new Material(assetManager,"Common/MatDefs/Misc/SimpleTextured.j3md");

    mat.setTexture("m_ColorMap", texture);

    textures = mat;

    }

    }

    }

    }



    private void readGeometry(String info, BufferedReader reader, List<ModelData> modelData) throws IOException {

    String[] args = info.split("\s");

    int numVertices = Integer.parseInt(args[2]);

    int numTriangles = Integer.parseInt(args[3]);

    ModelData data = new ModelData();

    data.vertexData.vertices=numVertices;

    data.vertexData.vertexBuffer = BufferUtils.createVector3Buffer(numVertices);

    data.vertexData.textureBuffer = BufferUtils.createVector2Buffer(numVertices);

    data.vertexData.normalBuffer = BufferUtils.createVector3Buffer(numVertices);

    float x,y,z,s,t;

    int i1,i2,i3;

    x=y=z=s=t=0.0f;

    String line = null;

    for (int i=0;i<numVertices;i++) {

    line = reader.readLine();

    currentLineNumber++;

    args = line.split("\s");

    x=Float.parseFloat(args[0]);

    y=Float.parseFloat(args[1]);

    z=Float.parseFloat(args[2]);

    s=Float.parseFloat(args[4]);

    t=Float.parseFloat(args[5]);

    data.vertexData.vertexBuffer.put(x).put(y).put(z);

    data.vertexData.normalBuffer.put(0).put(1).put(0);

    data.vertexData.textureBuffer.put(s).put(t);

    }

    Map<String,List<String[]>> textureTriMap = new HashMap<String,List<String[]>>();

    for (int i=0;i<numTriangles;i++) {

    args = reader.readLine().split(" ");

    currentLineNumber++;

    List<String[]> textureTriList = (List<String[]>)textureTriMap.get(args[0]);

    if (textureTriList == null) {

    textureTriList = new ArrayList<String[]>();

    textureTriMap.put(args[0], textureTriList);

    }

    textureTriList.add(args);

    }

    for(Map.Entry<String,List<String[]>> entry : textureTriMap.entrySet()) {

    String textureNumberStr = (String)entry.getKey();

    List<String[]> textureTriList = (List<String[]>)entry.getValue();



    int textureNumber = Integer.parseInt(textureNumberStr);

    // new texture segregated triangle list

    TriData triData = new TriData();

    triData.triangles = textureTriList.size();

    triData.textureNumber = textureNumber;

    triData.indicesBuffer = BufferUtils

    .createIntBuffer(triData.triangles*3);

    for(Iterator<String[]> j=textureTriList.iterator();j.hasNext():wink: {

    String[] triargs = (String[])j.next();

    i1=Integer.parseInt(triargs[1]);

    i2=Integer.parseInt(triargs[2]);

    i3=Integer.parseInt(triargs[3]);

    triData.indicesBuffer.put(i1).put(i2).put(i3);

    }

    data.triData.add(triData);

    }

    modelData.add(data);

    }





    }



    /**
  • Method to agressively attempt to find a file match for a given
  • texture name given that many models do not give a proper relative
  • path.

    */

    public static String findFileMatch(String directory, String entry, AssetManager assetManager) {

    // Try locating the file by appending the path to the directory

    String filename = directory + (String)entry;

    AssetKey<String> key = new AssetKey<String>(filename);

    if (assetManager.locateAsset(key)!=null)

    return filename;



    // Try locating the file by appending just the filename to the directory

    String useName = entry.toLowerCase();

    int lastPos = entry.lastIndexOf(’/’);

    if (lastPos == -1) {

    lastPos = entry.lastIndexOf(’’);

    }

    if (lastPos != -1) {

    useName = entry.substring(lastPos+1).toLowerCase();

    }



    filename = directory + useName;

    key = new AssetKey<String>(filename);

    if (assetManager.locateAsset(key)!=null)

    return filename;

    else

    return null;

    }



    @Override

    public Object load(AssetInfo info) throws IOException {

    logger.info(“reading HPS file:” + info.getKey().getName());

    Node modelNode = new Node(“model:” + info.getKey().getName());

    HPSModel model = null;

    List<HPSLoader.ModelData> modelDataList = null;

    try {

    model = new HPSModel(info);

    modelDataList = model.getModelData(0);

    }

    catch (Exception e) {

    logger.log(Level.SEVERE,“unable to load model:” + info.getKey().getName(),e);

    return modelNode;

    }

    logger.info(“model data list size=” + modelDataList.size());



    int triangleCount = 0, vertexCount = 0;;

    Geometry childMesh = null;

    for (HPSLoader.ModelData modelData : modelDataList) {

    for (HPSLoader.TriData triData : modelData.triData) {

    childMesh = new Geometry(“node”, new Mesh());



    if (triData.textureNumber != -1) {

    childMesh.setMaterial(model.textures[triData.textureNumber]);

    }



    childMesh.getMesh().setBuffer(Type.Position,3,modelData.vertexData.vertexBuffer);

    childMesh.getMesh().setBuffer(Type.Index,3,triData.indicesBuffer);

    childMesh.getMesh().setBuffer(Type.Normal,3,modelData.vertexData.normalBuffer);

    childMesh.getMesh().setBuffer(Type.TexCoord,2,modelData.vertexData.textureBuffer);



    modelNode.attachChild(childMesh);



    triangleCount += triData.triangles;

    vertexCount += modelData.vertexData.vertices;

    }

    }

    logger.info(info.getKey().getName() + " entity triangles=" + triangleCount
  • " entity vertices=" + vertexCount);

    return modelNode;

    }



    }

    [/java]
3 Likes

wow you’re on fire!! :wink:

Great! Thanks!

Since LWO is kinda popular I decided to check it on a model, but it crashed on the LWOB check, when I looked at the value that was there, it was LWO2. I guess there’s a new LWO format and your loader doesn’t support it?

Can you send the model? It works on all of the LWO models I have. They’re all missile & JDAM models used primarily by the Navy though, so they’re pretty simple.

http://www.jmonkeyengine.com/downloads/Tricycle.lwo

I added the lwo loader to the contributions repo as a jMP loader plugin:

http://code.google.com/p/jmonkeyplatform-contributions/source/browse/trunk/lightwave-support/src/com/jme3/scene/plugins/LWOLoader.java

@hazmat: PM me your googlecode address so I can add you to the project