Package com.l2client.app

Source Code of com.l2client.app.Assembler2

package com.l2client.app;

import java.util.HashMap;
import java.util.logging.Logger;

import com.jme3.animation.Skeleton;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.l2client.animsystem.jme.JMEAnimationController;
import com.l2client.asset.Asset;
import com.l2client.model.PartSet;
import com.l2client.model.WeaponSet;


/**
* A high level 3d model assembler, based on the @see PartSetManager model configuration.
* Templates for 3d models are named uniquely then all parts are looked up, from which the
* next possible permutation is chosen. The parts of this model are passed over to the
* low level assembler @see Assembler to finally create a jme3 3d model.
*
* models are invoked by calling the different getModel() methods.
*/
public class Assembler2 {
 
  private static Logger log = Logger.getLogger(Assembler2.class.getName());

  /**
   * returns a possible model identified by the template name. no batching and no
   * hw skinning is used. The model AnimationController is based on the l2client
   * FCOgre Animation controller @see JMEAnimationController.
   *
   * @param template  name of the model template from the partset configuration
   * @return a @see Node below which the 3d model and the animation controller is present
   */
  public static Node getModel(String template){
    Node n = getModelInternal(JMEAnimationController.class, template, false, false);
    return n;
  }

  /**
   * returns a possible model identified by the template name. no batching and no
   * hw skinning is used. The model AnimationController is based on the l2client
   * FCOgre Animation controller @see JMEAnimationController.
   * The model is rotated by - PI/2 around the x-axis
   *
   * @param template  name of the model template from the partset configuration
   * @return a @see Node below which the 3d model and the animation controller is present
   */
  public static Node getModel3(String template){
    Node n = getModelInternal(JMEAnimationController.class, template, false, false);
    n.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
    n.updateGeometricState();
   
    return n;
  }
 
  /**
   * returns a possible model identified by the template name. no batching and no
   * hw skinning is used. The model AnimationController is based on the l2client
   * FCOgre Animation controller @see JMEAnimationController.
   * The model is rotated by - PI/2 around the x-axis
   *
   * @param template  name of the model template from the partset configuration
   * @param optimized combine all mesh parts into one mesh using batch factory (should use same material)
   * @param hwSkinning hwSkinning desired or not
   * @return a @see Node below which the 3d model and the animation controller is present
   */
  public static Node getModel4(String template, boolean optimized, boolean hwSkinning){
    Node n = getModelInternal(JMEAnimationController.class, template, optimized, hwSkinning);
    n.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
    n.updateGeometricState();
   
    return n;
  }
   
//  private static void addController(Node model, Mesh [] meshes,
//      Skeleton skeleton, String animSet) {
//      //TODO move this out into AnimationManger
//      AnimControl c = new AnimControl(skeleton);//skeleton, animParts, template
//      c.createChannel();
//      c.setAnimationProvider(AnimationManager.get().getAnimationProvider(animSet));
//
//            model.addControl(new JMEAnimationController(c, animSet));
//            SkeletonControl skeletonControl = new SkeletonControl(meshes, skeleton);
//            model.addControl(skeletonControl);
//  }
 
  /**
   * Top of the template partset containing all sub parts
   * @param id
   * @return
   */
  public static PartSet getTopPart(String id){
    PartSet ret = Singleton.get().getPartManager().getPart("entity");
    if(ret != null)
      return ret.getPart(id);
    else return null;
  }
 
  /**
   * Retrieves from an entity the next material instances
   * @param top the top partset of this entity
   * @return  Hashmap of material names from this entity and the asset of the mat instance
   */
  public static HashMap<String, Asset> getMaterials(PartSet top){
    HashMap<String, Asset> materials = new HashMap<String, Asset>();
    PartSet det = top.getPart("mat");
    if(det != null){
    for( PartSet m : det.getParts()){
      String next = m.getNext();
      Asset a = new Asset(next,m.getName());
      Singleton.get().getAssetManager().loadAsset(a, false);
      materials.put(m.getName(),a);
    }
    } //FIXME else log waring!!!
//    } else
     
    return materials;
  }
 
//  public static ArrayList<Asset> getMeshes(PartSet top){
//    //get meshes (w.o. weapon sets)
//    ArrayList<Asset> meshArray = new ArrayList<Asset>();
//    PartSet det = top.getPart("mesh");
//    for( PartSet oSet : det.getParts()){
//      String name = oSet.getName();
//      if(name.startsWith("weapon") || name.startsWith("shield"))//skip weapon+shield model
//        continue;
//      String next = oSet.getNext();
//      Asset a = new Asset(next,name);
//      Singleton.get().getAssetManager().loadAsset(a, false);
//      meshArray.add(a);
//    }
//   
//    return meshArray;
//  }
// 
 
  /**
   * Retrieves one next instances with material information
   * @param top
   * @return
   */
  public static HashMap<Asset,String> getMeshesWithMaterial(PartSet top){
    //get meshes (w.o. weapon sets)
    HashMap<Asset,String> meshArray = new HashMap<Asset,String>();
    //mesh
    PartSet det = top.getPart("mesh");
      for( PartSet oSet : det.getParts()){
    //mesh part
        String name = oSet.getName();
        if(name.startsWith("weapon") || name.startsWith("shield"))//skip weapon+shield model
          continue;
    //materials
        for(PartSet matSet :oSet.getParts()){
          String mat = matSet.getName();
    //next mesh
          String next = matSet.getNext();
          Asset a = new Asset(next,name);
          Singleton.get().getAssetManager().loadAsset(a, false);
          meshArray.put(a,mat);
      }
    }
   
    return meshArray;
  }
 
  /**
   * Special handling of hair for player for example.
   * @param top the top partset
   * @param i    the nth hair style to chose
   * @return  the asset representing the desired hairstyle
   */
  public static Asset getHair(PartSet top, int i){
    Asset ret = null;
    PartSet det = top.getPart("mesh");
    if(det != null)
      det = det.getPart("hair");
    if(det != null){     
      String hair = null;
      if(i>=0){
        hair = det.get(i);
      }else{
        hair = det.getNext();
      }
      if(hair != null && !"".equals(hair)){
        ret = new Asset(hair,"hair");
        Singleton.get().getAssetManager().loadAsset(ret, false);
      }
    }
    return ret;
     
  }
 
  /**
   * Retrieves weapon configs for an entity
   * @param top entity (e.g. DwarfWarrior etc.)
   * @return the next weapon configuration
   */
  public static WeaponSet getWeaponset(PartSet top){
    PartSet det = top.getPart("weapon");
    if(det != null){
    String weaponSets = det.getNext();
//    String weaponSet = det.getPart(weaponSets).getNext();
    Asset ws = new Asset(weaponSets,det.getName());
    Singleton.get().getAssetManager().loadAsset(ws, true);
    //add weaponset meshes
    return (WeaponSet)ws.getBaseAsset();
    } else
      return null;
  }
 
  /**
   * Retrieves the next weapon meshes for an entity
   * @param top  the top entity (e.g. DwarfWarrior etc PartSet)
   * @param weapons  the waeponset to use for loading
   * @return
   */
  private static Asset[] getWeapons(PartSet top, WeaponSet weapons){
    if(weapons != null){
    PartSet det = top.getPart("mesh");
    PartSet p = det.getPart(weapons.getPrimhand());
    if(p == null)
      return null;
    String s = p.getNext();
    Asset prim = new Asset(s,p.getName());
    Singleton.get().getAssetManager().loadAsset(prim, false);
    p = det.getPart(weapons.getOffhand());
    //FIXME optionality not done here so far
    if(p != null){
      s = p.getNext();
      Asset secnd = new Asset(s,p.getName());
      Singleton.get().getAssetManager().loadAsset(secnd, false);
      return new Asset[]{prim,secnd};
    } else
      return new Asset []{prim};
   
    } else return null;
  }
 
  private static HashMap<Asset, String> getWeaponGeoms(PartSet top,
      WeaponSet weapons) {
    HashMap<Asset, String> ret = new HashMap<Asset, String>();

    if (weapons != null) {
      PartSet det = top.getPart("mesh");
      PartSet p = det.getPart(weapons.getPrimhand());
      if (p == null) {
        log.severe("Failed to load any weapons for "+top.getName()+" and weaponset "+weapons);
        return ret;
      }
      String mat = p.getNext();
      for(PartSet set : p.getParts()) {
      Asset prim = new Asset(set.getNext(), p.getName());
      Singleton.get().getAssetManager().loadAsset(prim, false);
      ret.put(prim, mat);
      }
      p = det.getPart(weapons.getOffhand());
      // FIXME optionality not done here so far
      if (p != null) {
        mat = p.getNext();
        for(PartSet set : p.getParts()) {
        Asset prim = new Asset(set.getNext(), p.getName());
        Singleton.get().getAssetManager().loadAsset(prim, false);
        ret.put(prim, mat);
        }
      }
    }
    if(ret.size() <=0)
      log.severe("Failed to load any weapons for "+top.getName()+" and weaponset "+weapons);
    return ret;
  }

  public static HashMap<String, PartSet> getAnimations(/*PartSet top, */String animSet, String defaultSet) {
    HashMap<String, PartSet> animParts = new HashMap<String, PartSet>();
    PartSet parts = Singleton.get().getPartManager().getPart("anim");
    if(parts == null)
      return animParts;
    PartSet det = parts.getPart(animSet);
    if( det != null )
//      for(PartSet e : det.getParts()){
        animParts = Singleton.get().getAnimManager().precacheAnimations(det);
//      }
    if(defaultSet != null){
      det = parts.getPart(defaultSet);
      if(det != null){
        Singleton.get().getAnimManager().setDefault(animSet, defaultSet);
        Singleton.get().getAnimManager().precacheAnimations(det);
      }
    }
     
    return animParts;
  }

  public static Skeleton getSkeleton(PartSet top) {
    //get skeleton
    PartSet det = top.getPart("skel");
    //FIXME always the 1.0 or is this deprecated?
    return Singleton.get().getSkeletonManager().getSkeleton(det.getNext(), 1.0f);
  }

  /**
   * internal orchestration of model parts lookup and assembly
   *
   * @param controller
   * @param template
   * @param optimized
   * @param hwSkinning
   * @return
   */
  private static Node getModelInternal(Class<?> controller, String template, boolean optimized, boolean hwSkinning){

    PartSet top = getTopPart(template);
    //FIMXE error handling
    if(top == null) {
      new Exception("Failed to find temple <"+template+"> in megaset").printStackTrace();
      return new Node("NULL");
    }
   
    HashMap<String, Asset> materials = getMaterials(top);

    WeaponSet weapons = getWeaponset(top);

    HashMap<Asset, String> meshArray = getMeshesWithMaterial(top);
   
    addWeaponSetToMeshMap(top, weapons, meshArray);

    Skeleton skel = getSkeleton(top);

    getAnimations(/*top, */weapons.getAnimSet(), weapons.getDefaultSet());

    Node n = assembleModel(template,meshArray,materials,skel,weapons.getAnimSet(), optimized, hwSkinning);
       
    return n;
  }
 
  public static void addWeaponSetToMeshMap(PartSet top, WeaponSet weapons,
      HashMap<Asset, String> meshes) {
      HashMap<Asset, String> a = getWeaponGeoms(top, weapons);
      meshes.putAll(a);
  }



  /** pass it all over to the low level assebler
   *
   * @param template
   * @param meshArray
   * @param materials
   * @param skel
   * @param animSet
   * @param optimized
   * @param hwSkinnig
   * @return
   */
  private static Node assembleModel(String template,
      HashMap<Asset, String> meshArray, HashMap<String, Asset> materials,
      Skeleton skel, String animSet, boolean optimized, boolean hwSkinnig) {
    Assembler as = new Assembler();
    as.setUseOptimization(optimized);
    as.setUseHWSkinning(hwSkinnig);
    as.setSkeleton(skel);
    unpackMeshesIntoAssembler(meshArray, materials, as);
     
    as.setAnimParts(animSet);
    Node n = as.getModel();
    n.setName(template);
    return n;
  }

  public static void unpackMeshesIntoAssembler(
      HashMap<Asset, String> meshArray, HashMap<String, Asset> materials,
      Assembler assembler) {
    for(Asset a : meshArray.keySet()){
      Object n = a.getBaseAsset();
      if(n != null){
        if(n instanceof Geometry){
          Asset mat = materials.get(meshArray.get(a));
          if(mat != null){
            Material m = (Material)mat.getBaseAsset();
            if(m != null){
              //prepare rim light shader for selection highlighting
              m.setColor("RimLighting", ColorRGBA.BlackNoAlpha);//new ColorRGBA(1f, 0f, 0f, 12f));//this was for a test had to set the value to 12 for a really good noticable look
              //this must be a clone for hardware skinning
              ((Geometry)n).setMaterial(m.clone());
            } else
              log.severe("Material "+mat.getLocation()+" not found is missing for "+a.getLocation());
          }else
            log.severe("Material is missing for "+a.getLocation());
         
          assembler.addMesh(a.getName(), (Geometry)n , false);
        }
        else
          log.severe("Loaded Mesh asset which is not a Mesh but a:"+n.getClass().getName());
      }
      else
        log.severe("BaseAsset not found:"+a.getName()+", "+a.getLocation());
    }
  }
}
TOP

Related Classes of com.l2client.app.Assembler2

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.