Package org.jdesktop.wonderland.client.jme.cellrenderer

Source Code of org.jdesktop.wonderland.client.jme.cellrenderer.ModelRenderer

/**
* Open Wonderland
*
* Copyright (c) 2010 - 2011, Open Wonderland Foundation, All Rights Reserved
*
* Redistributions in source code form must reproduce the above
* copyright and this condition.
*
* The contents of this file are subject to the GNU General Public
* License, Version 2 (the "License"); you may not use this file
* except in compliance with the License. A copy of the License is
* available at http://www.opensource.org/licenses/gpl-license.php.
*
* The Open Wonderland Foundation designates this particular file as
* subject to the "Classpath" exception as provided by the Open Wonderland
* Foundation in the License file that accompanied this code.
*/

/**
* Project Wonderland
*
* Copyright (c) 2004-2010, Sun Microsystems, Inc., All Rights Reserved
*
* Redistributions in source code form must reproduce the above
* copyright and this condition.
*
* The contents of this file are subject to the GNU General Public
* License, Version 2 (the "License"); you may not use this file
* except in compliance with the License. A copy of the License is
* available at http://www.opensource.org/licenses/gpl-license.php.
*
* Sun designates this particular file as subject to the "Classpath"
* exception as provided by Sun in the License file that accompanied
* this code.
*/
package org.jdesktop.wonderland.client.jme.cellrenderer;

import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Geometry;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.RenderState;
import com.jme.scene.state.TextureState;
import java.net.URL;
import java.util.Map;
import java.util.logging.Logger;
import org.jdesktop.mtgame.Entity;
import org.jdesktop.mtgame.RenderComponent;
import org.jdesktop.mtgame.RenderComponent.AttachPointNode;
import org.jdesktop.mtgame.RenderUpdater;
import org.jdesktop.wonderland.client.cell.Cell;
import org.jdesktop.wonderland.client.cell.CellStatistics.TimeCellStat;
import org.jdesktop.wonderland.client.cell.ModelCellComponent;
import org.jdesktop.wonderland.client.jme.ClientContextJME;
import org.jdesktop.wonderland.client.jme.artimport.DeployedModel;
import org.jdesktop.wonderland.client.jme.artimport.LoaderManager;
import org.jdesktop.wonderland.client.jme.artimport.ModelLoader;
import org.jdesktop.wonderland.client.jme.utils.traverser.ProcessNodeInterface;
import org.jdesktop.wonderland.client.jme.utils.traverser.TreeScan;
import org.jdesktop.wonderland.common.cell.state.ModelCellComponentServerState.TransparencyMode;

/**
*
* @author paulby
*/
public class ModelRenderer extends BasicRenderer {
    private URL deployedModelURL;
    private Vector3f modelTranslation = null;
    private Quaternion modelRotation = null;
    private Vector3f modelScale = null;

    private ModelCellComponent modelComponent = null;
    private DeployedModel deployedModel = null;

    private TransparencyMode transparency = null;

    public ModelRenderer(Cell cell, URL deployedModelURL) {
        this(cell, deployedModelURL, null, null, null, null);
    }

    public ModelRenderer(Cell cell, ModelCellComponent modelComponent) {
        this(cell, null, modelComponent);
    }

    public ModelRenderer(Cell cell, DeployedModel deployedModel) {
        this(cell, deployedModel, null);
    }

    public ModelRenderer(Cell cell, DeployedModel deployedModel, ModelCellComponent modelComponent) {
        super(cell);
        this.deployedModel = deployedModel;
        this.modelComponent = modelComponent;
    }

    public ModelRenderer(Cell cell,
            URL deployedModelURL,
            Vector3f modelTranslation,
            Quaternion modelRotation,
            Vector3f modelScale,
            Map<String, Object> properties) {
        super(cell);
        this.deployedModelURL = deployedModelURL;
        this.modelTranslation = modelTranslation;
        this.modelRotation = modelRotation;
        this.modelScale = modelScale;
    }

    @Override
    protected Node createSceneGraph(Entity entity) {
        long startTime = System.currentTimeMillis();
        TimeCellStat loadTime = new TimeCellStat("loadtime", "Model Load Time");
       
        try {
            if (modelComponent!=null) {
                return modelComponent.loadModel(entity);
            }

            if (deployedModel!=null) {
                ModelLoader loader = deployedModel.getModelLoader();
                if (loader==null) {
                    logger.warning("No loader for model "+deployedModel.getModelURL());
                    return new Node("No Loader");
                }
                Node ret = loader.loadDeployedModel(deployedModel, entity);
                return ret;
            }

            ModelLoader loader = LoaderManager.getLoaderManager().getLoader(deployedModelURL);
            if (loader==null) {
                logger.warning("No loader for model "+deployedModel.getModelURL());
                return new Node("No Loader");
            }
            deployedModel = new DeployedModel(deployedModelURL, loader);
            deployedModel.setModelTranslation(modelTranslation);
            deployedModel.setModelRotation(modelRotation);
            deployedModel.setModelScale(modelScale);

            return loader.loadDeployedModel(deployedModel, entity);
        } finally {
            // record statistics
            loadTime.setValue(System.currentTimeMillis() - startTime);
            getCell().getCellCache().getStatistics().add(getCell(), loadTime);
        }
    }

    @Override
    protected void addDefaultComponents(Entity entity, Node rootNode) {
        super.addDefaultComponents(entity, rootNode);

        // update transparency now that the scene root is set
        if (transparency != null) {
            applyTransparency(TransparencyMode.DEFAULT, transparency);
        }
    }

    /**
     * For the renderer to reload the scene graph. This is required if the user
     * changes properties of the graph, such as optimization levels. The detach of
     * the current graph and loading of the new graph are done asynchronously, this
     * method returns immediately.
     */
    public void reload() {
        if (sceneRoot!=null) {
            ClientContextJME.getWorldManager().addRenderUpdater(new RenderUpdater() {
                public void update(Object arg0) {
                    ((Node)arg0).removeFromParent();

                    // TODO DONT do the load (createSceneGraph) on the render thread
                    sceneRoot = createSceneGraph(entity);
                    rootNode.attachChild(sceneRoot);
                    ClientContextJME.getWorldManager().addToUpdateList(rootNode);
                }
            }, sceneRoot);
        }
    }

    /**
     * Change the transparency properties of the model
     * @param transparency the new transparency
     */
    public void setTransparency(TransparencyMode transparency) {
        if (this.transparency == transparency) {
            // ignore
            return;
        }

        TransparencyMode old = this.transparency;
        this.transparency = transparency;

        if (sceneRoot != null) {
            applyTransparency(old, transparency);
        }
    }

    protected void applyTransparency(TransparencyMode oldTM,
                                     TransparencyMode newTM)
    {
        final Transparency oldTrans = Transparency.get(oldTM);
        final Transparency newTrans = Transparency.get(newTM);

        // make the change on the render thread
        ClientContextJME.getWorldManager().addRenderUpdater(new RenderUpdater() {
            public void update(Object arg0) {
                TreeScan.findNode((Spatial) arg0, new ProcessNodeInterface() {
                    public boolean processNode(Spatial node) {
                        // stop if we cross an entity barier
                        if (node instanceof AttachPointNode) {
                            return false;
                        }

                        // load the blend state (if any)
                        BlendState as = (BlendState) node.getRenderState(RenderState.StateType.Blend);
                        if (as != null) {
                            // unapply the old state (getting us back to base state)
                            oldTrans.unapply(node, as);

                            // apply the new state
                            newTrans.apply(node, as);
                        }

                        return true;
                    }
                });
            }
        }, sceneRoot);
    }

    @Override
    protected void cleanupSceneGraph(Entity entity) {
        RenderComponent rc = entity.getComponent(RenderComponent.class);
        if (rc!=null) {
            ClientContextJME.getWorldManager().addRenderUpdater(new RenderUpdater() {

                public void update(Object arg0) {
                    TreeScan.findNode((Spatial) arg0, new ProcessNodeInterface() {
                        public boolean processNode(Spatial node) {
                            if (node instanceof Geometry) {
                                ((Geometry)node).clearBuffers();
                                TextureState ts = (TextureState) node.getRenderState(RenderState.RS_TEXTURE);
                                // deleteAll is too aggressive, it deletes other copies of the same texture
//                                if (ts!=null)
//                                    ts.deleteAll(false);
                            }
                            return true;
                        }
                    });
                }
            }, rc.getSceneRoot());
        }

        deployedModel = null;
    }


    private enum Transparency {
        DEFAULT,
        INVERSE {
            @Override
            public void apply(Spatial target, BlendState as) {
                ColorRGBA c = as.getConstantColor();
                if (c != null) {
                    c.set(1.0f - c.r, 1.0f - c.g, 1.0f - c.b, 1.0f - c.a);
                    as.setConstantColor(c);
                }
            }

            @Override
            public void unapply(Spatial target, BlendState as) {
                // apply will reverse the transparency, bringing it back
                // to the original level
                apply(target, as);
            }
        },
        NONE {
            @Override
            public void apply(Spatial target, BlendState as) {
                // disable blending & transparency
                as.setEnabled(false);
                target.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
            }

            @Override
            public void unapply(Spatial target, BlendState as) {
                // enable blending & transparency
                as.setEnabled(true);
                target.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
            }
        };

        // default does nothing -- we are already in the start state
        void apply(Spatial target, BlendState as) {}
        void unapply(Spatial target, BlendState as) {}

        static Transparency get(TransparencyMode mode) {
            switch (mode) {
                case INVERSE:
                    return Transparency.INVERSE;
                case NONE:
                    return Transparency.NONE;
                default:
                    return Transparency.DEFAULT;
            }
        }
    };
}
TOP

Related Classes of org.jdesktop.wonderland.client.jme.cellrenderer.ModelRenderer

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.