LODNode.java :  » Game » infinitewars » logic » nodes » lod » Java Open Source

Java Open Source » Game » infinitewars 
infinitewars » logic » nodes » lod » LODNode.java
package logic.nodes.lod;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.Callable;

import logic.nodes.collision.CollidableNode;
import logic.nodes.collision.DummyType;
import logic.nodes.lod.blocks.LeafBlock;
import logic.ships.mothership.MotherShip;
import logic.weapons.Weapon;

import settings.GraphicSettings;

import com.jme.bounding.BoundingBox;
import com.jme.bounding.BoundingVolume;
import com.jme.image.Texture;
import com.jme.math.Vector3f;
import com.jme.scene.BillboardNode;
import com.jme.scene.DistanceSwitchModel;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.TriMesh;
import com.jme.scene.lod.DiscreteLodNode;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.RenderState.StateType;
import com.jme.util.GameTaskQueueManager;

import fileHandling.ModelImporter;
import fileHandling.TextureLoader;
import gameStates.absGamesStates.AbsIngameState;

public abstract class LODNode extends CollidableNode {
  
  private static final long serialVersionUID = 1L;
  
  protected String geomQual, texQual, normQual, specQual, bumpQual, shaderQual;
  protected float currentLOD;
  protected Collection<Node> detachedSlots, lodNodes;
  protected HashMap<TriMesh, BoundingVolume> meshBounds;
  protected HashMap<TriMesh, Vector3f> meshDirs;
  private int maxSwitches;
  
  public LODNode(String path, String title, Node model, AbsIngameState ingameState) {
    this(path, title, model, DummyType.None, ingameState);
  }
  
  public LODNode(String path, String title, Node model, DummyType dummyType, AbsIngameState ingameState) {
    super(path, title, model, dummyType, ingameState);
    
    updateGeometryQuality();
  }
  
  public boolean updateGeometryQuality() {
    if(geomQual != null && 
    geomQual.equals(GraphicSettings.get().getGeometryQuality()) 
    && currentLOD == GraphicSettings.get().getLOD()) return false;
    
    setGraphicSettings();
    
    Node newModel = ModelImporter.getModel(path);
    setModel(getLODNode(newModel));
    assert(getModel() != null);
    updateRenderState();
    
    if(isLarge()) {
      int childIndex = 2;
      if(geomQual.equals("medium")) childIndex = 1;
      else if(geomQual.equals("low")) childIndex = 0;
      
      getLODModel().setActiveChild(childIndex);
      
      meshBounds = new HashMap<TriMesh, BoundingVolume>();
      meshDirs = new HashMap<TriMesh, Vector3f>();
      
      getTriMeshes((Node)getLODModel().getChild(childIndex));
    }
    
    return true;
  }
  
  public void removeBoundControllerOf(TriMesh mesh) {
    boundControllers.remove(mesh);
    lockNode();
  }
  
  protected void getTriMeshes(Node parent) {
    for(Spatial child : parent.getChildren()) {
      if(child instanceof Node) getTriMeshes((Node)child);
      else if(child instanceof TriMesh) {
        TriMesh mesh = (TriMesh)child;
        mesh.setModelBound(new BoundingBox());
        mesh.updateModelBound();
        mesh.updateWorldBound();
        TriMeshBoundController c = new TriMeshBoundController(mesh, this, meshBounds, meshDirs);
        boundControllers.put(mesh, c);
        mesh.addController(c);
      }
    }
  }
  
  protected DiscreteLodNode getLODNode(Node maxQualModel) {
    String geomQual = GraphicSettings.get().getGeometryQuality();
    maxSwitches = 6;
    if(geomQual.equals("medium")) maxSwitches = 5;
    else if(geomQual.equals("low")) maxSwitches = 4;
    
    detachedSlots = new HashSet<Node>();
    lodNodes = new ArrayList<Node>();
    
    DistanceSwitchModel switchModel = new DistanceSwitchModel(maxSwitches);
    DiscreteLodNode dlodNode = getDiscreteLodNode(switchModel);
    
    float notVisibleDist = LeafBlock.VIEW_DIST - LeafBlock.MIN_LOD_VIEW_DIST;
    float visibleDist = LeafBlock.MIN_LOD_VIEW_DIST + (notVisibleDist * GraphicSettings.get().getLOD());
    float distDiv = visibleDist / maxSwitches;
    float dist = distDiv * getDistanceFactor();
    assert(dist > 0f);
    
    String texQual = GraphicSettings.get().getTextureQuality();
    
    setScaleOf(maxQualModel);
    updateTextureQualityOf(maxQualModel, texQual);
    dlodNode.attachChild(maxQualModel);
    switchModel.setModelDistance(0, 0f, dist);
    detachedSlots.add(maxQualModel);
    lodNodes.add(maxQualModel);
    
    int lastSwitch = maxSwitches;
    boolean isMS = this instanceof MotherShip;
    boolean useBB = !(this instanceof Weapon || isMS);
    boolean lastTillInf = isMS;
    for(int i = 1; i <= lastSwitch ; i++) {
      String newTexQual = ModelImporter.nextLevel(texQual, true);
      Node node = null;
      if(i != lastSwitch) {
        if(newTexQual != null) texQual = newTexQual;
        
        geomQual = ModelImporter.nextLevel(geomQual, true);
        assert(geomQual != null);
        
        float maxDist = (i + 1) * dist;
        if(i == lastSwitch - 1 && lastTillInf) maxDist = Float.POSITIVE_INFINITY;
        switchModel.setModelDistance(i, i * dist, maxDist);
        
        node = ModelImporter.getModelOfQuality(path, geomQual);
        assert(node != null);
        setScaleOf(node);
        
        updateTextureQualityOf(node, texQual);
        
        detachedSlots.add(node);
      } else if(useBB) {
        node = new Node("Dummy_BBNode");
        node.attachChild(new Quad("Dummy_Quad"));
        switchModel.setModelDistance(i, i * dist, Float.POSITIVE_INFINITY);
        addController(new BBNodeController(this));
      } else break;
      
      dlodNode.attachChildAt(node, i);
      lodNodes.add(node);
      if(i == lastSwitch - 1 && lastTillInf) break;
    }
    
    assert(ModelImporter.nextLevel(geomQual, true) == null);
    
    return dlodNode;
  }
  
  public void setBillboardNode(BillboardNode bbNode) {
    getLODModel().attachChildAt(bbNode, maxSwitches);
  }
  
  public void updateTextureFilters() {
    for(Node node : lodNodes) {
      updateTextureFilters(node);
    }
    updateRenderState();
  }
  
  protected void updateTextureFilters(Node model) {
    if(model == null || model.getChildren() == null) return;
    for(Spatial child : model.getChildren()) {
      if(child instanceof Node) updateTextureFilters((Node)child);
      else {
        TextureState ts = (TextureState)child.getRenderState(StateType.Texture);
        if(ts == null) continue;
        Texture tex = ts.getTexture();
        if(tex == null) continue;
        TextureLoader.upateTextureFilter(tex);
      }
    }
  }
  
  public boolean updateTextureQuality() {
    if(texQual != null && 
    texQual.equals(GraphicSettings.get().getTextureQuality()) &&
    normQual != null && 
    normQual.equals(GraphicSettings.get().getNormalQuality()) &&
    specQual != null && 
    specQual.equals(GraphicSettings.get().getSpecularQuality()) &&
    bumpQual != null && 
    bumpQual.equals(GraphicSettings.get().getBumpQuality()) &&
    shaderQual != null && 
    shaderQual.equals(GraphicSettings.get().getShaderQuality())) return false;
    
    setGraphicSettings();
    
    String tempQual = texQual;
    for(Node child : lodNodes) {
      updateTextureQualityOf(child, tempQual);
      String newTexQual = ModelImporter.nextLevel(tempQual, true);
      if(newTexQual != null) tempQual = newTexQual;
    }
    
    updateRenderState();
    
    return true;
  }
  
  protected void setGraphicSettings() {
    GraphicSettings settings = GraphicSettings.get();
    geomQual = settings.getGeometryQuality();
    currentLOD = settings.getLOD();
    
    texQual = settings.getTextureQuality();
    normQual = settings.getNormalQuality();
    specQual = settings.getSpecularQuality();
    bumpQual = settings.getBumpQuality();
    shaderQual = settings.getShaderQuality();
  }
  
  protected void updateTextureQualityOf(Node model, String quality) {
    assert(quality != null && model != null && model.getChildren() != null);
    
    for(Spatial child : model.getChildren()) {
      if(child instanceof Node && ((Node)child).getChildren() != null) 
        updateTextureQualityOf((Node)child, quality);
      else if(child instanceof TriMesh) {
        TextureLoader.updateTextureQuality((TriMesh)child, quality);
        child.updateRenderState();
      }
    }
  }
  
  public Collection<TriMesh> getTriMeshes() { return meshBounds.keySet(); }
  
  public BoundingVolume getTriMeshBounding(TriMesh mesh) { return meshBounds.get(mesh); }
  
  public Vector3f getTriMeshDir(TriMesh mesh) { return meshDirs.get(mesh); }
  
  public DiscreteLodNode getLODModel() { return (DiscreteLodNode)getModel(); }
  
  public Node getActiveLODModel() {
    DiscreteLodNode lod = getLODModel();
    return (Node)lod.getChild(lod.getActiveChild());
  }
  
  protected DiscreteLodNode getDiscreteLodNode(DistanceSwitchModel switchModel) {
    return new DiscreteLodNode("LOD-Node", switchModel);
  }
  
  protected float getDistanceFactor() { return 1f; }
  
  public float getDefaultScale() { return 0.08f; }
  
  protected void setScaleOf(Spatial child) {
    child.setLocalScale(getDefaultScale());
  }
  
  public void updateGraphicSettings() {
    try {
      GameTaskQueueManager.getManager().update(new Callable<Void>() {
        @Override
        public Void call() throws Exception {
          if(!updateGeometryQuality() && !updateTextureQuality()) updateTextureFilters();
          return null;
        }
      }).get();
    } catch(Exception e) {}
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.