Package com.l2client.app

Source Code of com.l2client.app.Assembler

package com.l2client.app;

import java.util.HashMap;
import java.util.HashSet;

import jme3tools.optimize.GeometryBatchFactory;

import com.jme3.animation.AnimControl;
import com.jme3.animation.Skeleton;
import com.jme3.animation.SkeletonControl;
import com.jme3.material.Material;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
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;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.VertexBuffer.Usage;
import com.l2client.animsystem.jme.BoundsUpdateControl;
import com.l2client.animsystem.jme.JMEAnimationController;

/**
* A low level 3d model assembler. Add up meshes for body parts, a skeleton and the
* animation partset provider and assembles the final jme animated model.
*
* Used to have several base meshes and create permutations thereof
*/
public class Assembler {

  Node model = new Node();
  Skeleton skeleton = null;
  HashMap<String, Geometry> meshes = new HashMap<String, Geometry>();
  private String animSet;
  private boolean useOptimization = false;
  private boolean useHWSkinning = true;


  /**
   * @param useHWSkinning true if hardware/vertex skinnig is to be used
   */
  public void setUseHWSkinning(boolean useHWSkinning) {
    this.useHWSkinning = useHWSkinning;
  }


  /**
   * @param useOptimization true if optimization should be used
   */
  public void setUseOptimization(boolean useOptimization) {
    this.useOptimization = useOptimization;
  }


  private boolean isModelComplete(){
    if(skeleton != null && meshes.size() > 0 )
      return true;
   
    return false;
  }


  public void setSkeleton(Skeleton skel) {
    this.skeleton = skel;
    checkForUpdate();
  }

  public void addMesh(String name, Geometry mesh, boolean fireCheck) {
    this.meshes.put(name, mesh);
    if(fireCheck)
      checkForUpdate();
  }

  public void removeMesh(String name) {
    this.meshes.remove(name);
    checkForUpdate();
  }
 
  public HashMap<String, Geometry> getMeshes(){
    return meshes;
  }

  private void checkForUpdate() {
    if(isModelComplete()){
      int cntrls = model.getNumControls();
      for(int i = 0;i<cntrls;i++)
        model.removeControl(model.getControl(0));

      model.detachAllChildren();
     
      compileModel(model, meshes.values().toArray(new Geometry[meshes.size()]), false, skeleton);//, animProvider.getClass());
    }
  }

  private Node compileModel(Node model, Geometry[] geoms, boolean/** not used atm*/ shared, final Skeleton skeleton) {

        if (geoms != null) {
           
            Mesh[] meshes = new Mesh[geoms.length];
           
            HashSet<Material> materials = new HashSet<Material>();

            // generate bind pose for mesh and add to skin-list
            // ONLY if not using shared geometry
            // This includes the shared geoemtry itself actually
            for (int i = 0; i < geoms.length; i++) {
              meshes[i] = geoms[i].getMesh().cloneForAnim();

              Geometry g = new Geometry(geoms[i].getName(), meshes[i]);
              Material m = geoms[i].getMaterial();
              g.setMaterial(m);
              materials.add(m);
                model.attachChild(g);
            }

            if(useOptimization) {
              model = GeometryBatchFactory.optimize(model, false);
              //fix for bug in batchfactory removing empty hw buffers
              fixHWModels(model);
            }
           
            Skeleton skel = new Skeleton(skeleton);
          //TODO move this out into AnimationManger
      AnimControl c = new AnimControl(skel);//skeleton, animParts, template
      c.createChannel();
      c.setAnimationProvider(Singleton.get().getAnimManager().getAnimationProvider(animSet));
            model.addControl(new JMEAnimationController(c,animSet));
            SkeletonControl skeletonControl = new SkeletonControl(skel);
            model.addControl(skeletonControl);

            skeletonControl.setHardwareSkinningPreferred(useHWSkinning);

            BoundsUpdateControl bc = new BoundsUpdateControl();
            bc.setSkeleton(skel);
            model.addControl(bc);
            model.setShadowMode(ShadowMode.CastAndReceive);
           
        }
        return model;
    }

  private void fixHWModels(Spatial model) {
    if(model instanceof Geometry){
      fixHWSkinningBuffers(((Geometry)model).getMesh());
      return;
    } else {
      if(model instanceof Node){
        Node n = (Node) model;
        for(Spatial c : n.getChildren())
          fixHWModels(c);
      }
    }
  }


  //FIXME for old mesh format create empty HWSkinning buffers
  private void fixHWSkinningBuffers(Mesh mesh) {
        //creating empty buffers for HW skinning
        //the buffers will be setup if ever used.
    //setting usage to cpuOnly so that the buffer is not send empty to the GPU 
    VertexBuffer indicesHW = mesh.getBuffer(Type.HWBoneIndex);
    if(indicesHW == null){
      indicesHW = new VertexBuffer(Type.HWBoneIndex);
      indicesHW.setUsage(Usage.CpuOnly);
      mesh.setBuffer(indicesHW);
    }

        VertexBuffer weightsHW = mesh.getBuffer(Type.HWBoneWeight);
        if(weightsHW == null) {
          weightsHW = new VertexBuffer(Type.HWBoneWeight);
            weightsHW.setUsage(Usage.CpuOnly);
            mesh.setBuffer(weightsHW);
        }
      
             
  }


  public Node getModel() {
    checkForUpdate();
    return model;
  }


  public void setAnimParts(String animSet) {
    this.animSet = animSet;
  }
}
TOP

Related Classes of com.l2client.app.Assembler

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.