Package com.ardor3d.scenegraph.extension

Source Code of com.ardor3d.scenegraph.extension.Skybox

/**
* Copyright (c) 2008-2012 Ardor Labs, Inc.
*
* This file is part of Ardor3D.
*
* Ardor3D is free software: you can redistribute it and/or modify it
* under the terms of its license which may be found in the accompanying
* LICENSE file or at <http://www.ardor3d.com/LICENSE>.
*/

package com.ardor3d.scenegraph.extension;

import java.io.IOException;

import com.ardor3d.image.Texture;
import com.ardor3d.image.Texture.WrapMode;
import com.ardor3d.math.Matrix3;
import com.ardor3d.math.Vector3;
import com.ardor3d.renderer.Renderer;
import com.ardor3d.renderer.queue.RenderBucketType;
import com.ardor3d.renderer.state.FogState;
import com.ardor3d.renderer.state.RenderState;
import com.ardor3d.renderer.state.RenderState.StateType;
import com.ardor3d.renderer.state.TextureState;
import com.ardor3d.renderer.state.ZBufferState;
import com.ardor3d.scenegraph.Node;
import com.ardor3d.scenegraph.hint.CullHint;
import com.ardor3d.scenegraph.hint.LightCombineMode;
import com.ardor3d.scenegraph.hint.TextureCombineMode;
import com.ardor3d.scenegraph.shape.Quad;
import com.ardor3d.util.export.CapsuleUtils;
import com.ardor3d.util.export.InputCapsule;
import com.ardor3d.util.export.OutputCapsule;

/**
* A Box made of textured quads that simulate having a sky, horizon and so forth around your scene. Either attach to a
* camera node or update on each frame to set this skybox at the camera's position.
*/
public class Skybox extends Node {

    public enum Face {
        /** The +Z side of the skybox. */
        North,
        /** The -Z side of the skybox. */
        South,
        /** The -X side of the skybox. */
        East,
        /** The +X side of the skybox. */
        West,
        /** The +Y side of the skybox. */
        Up,
        /** The -Y side of the skybox. */
        Down;
    }

    private float _xExtent;
    private float _yExtent;
    private float _zExtent;

    private Quad[] _skyboxQuads;

    public Skybox() {}

    /**
     * Creates a new skybox. The size of the skybox and name is specified here. By default, no textures are set.
     *
     * @param name
     *            The name of the skybox.
     * @param xExtent
     *            The x size of the skybox in both directions from the center.
     * @param yExtent
     *            The y size of the skybox in both directions from the center.
     * @param zExtent
     *            The z size of the skybox in both directions from the center.
     */
    public Skybox(final String name, final float xExtent, final float yExtent, final float zExtent) {
        super(name);

        _xExtent = xExtent;
        _yExtent = yExtent;
        _zExtent = zExtent;

        initialize();
    }

    /**
     * Set the texture to be displayed on the given face of the skybox. Replaces any existing texture on that face.
     *
     * @param face
     *            the face to set
     * @param texture
     *            The texture for that side to assume.
     * @throws IllegalArgumentException
     *             if face is null.
     */
    public void setTexture(final Face face, final Texture texture) {
        if (face == null) {
            throw new IllegalArgumentException("Face can not be null.");
        }

        _skyboxQuads[face.ordinal()].clearRenderState(RenderState.StateType.Texture);
        setTexture(face, texture, 0);
    }

    /**
     * Set the texture to be displayed on the given side of the skybox. Only replaces the texture at the index specified
     * by textureUnit.
     *
     * @param face
     *            the face to set
     * @param texture
     *            The texture for that side to assume.
     * @param textureUnit
     *            The texture unite of the given side's TextureState the texture will assume.
     */
    public void setTexture(final Face face, final Texture texture, final int textureUnit) {
        // Validate
        if (face == null) {
            throw new IllegalArgumentException("Face can not be null.");
        }

        TextureState ts = (TextureState) _skyboxQuads[face.ordinal()]
                .getLocalRenderState(RenderState.StateType.Texture);
        if (ts == null) {
            ts = new TextureState();
        }

        // Initialize the texture state
        ts.setTexture(texture, textureUnit);
        ts.setEnabled(true);

        texture.setWrap(WrapMode.EdgeClamp);

        // Set the texture to the quad
        _skyboxQuads[face.ordinal()].setRenderState(ts);

        return;
    }

    public Texture getTexture(final Face face) {
        if (face == null) {
            throw new IllegalArgumentException("Face can not be null.");
        }
        return ((TextureState) _skyboxQuads[face.ordinal()].getLocalRenderState(RenderState.StateType.Texture))
                .getTexture();
    }

    public void initialize() {

        // Skybox consists of 6 sides
        _skyboxQuads = new Quad[6];

        // Create each of the quads
        _skyboxQuads[Face.North.ordinal()] = new Quad("north", _xExtent * 2, _yExtent * 2);
        _skyboxQuads[Face.North.ordinal()].setRotation(new Matrix3().fromAngles(0, Math.toRadians(180), 0));
        _skyboxQuads[Face.North.ordinal()].setTranslation(new Vector3(0, 0, _zExtent));
        _skyboxQuads[Face.South.ordinal()] = new Quad("south", _xExtent * 2, _yExtent * 2);
        _skyboxQuads[Face.South.ordinal()].setTranslation(new Vector3(0, 0, -_zExtent));
        _skyboxQuads[Face.East.ordinal()] = new Quad("east", _zExtent * 2, _yExtent * 2);
        _skyboxQuads[Face.East.ordinal()].setRotation(new Matrix3().fromAngles(0, Math.toRadians(90), 0));
        _skyboxQuads[Face.East.ordinal()].setTranslation(new Vector3(-_xExtent, 0, 0));
        _skyboxQuads[Face.West.ordinal()] = new Quad("west", _zExtent * 2, _yExtent * 2);
        _skyboxQuads[Face.West.ordinal()].setRotation(new Matrix3().fromAngles(0, Math.toRadians(270), 0));
        _skyboxQuads[Face.West.ordinal()].setTranslation(new Vector3(_xExtent, 0, 0));
        _skyboxQuads[Face.Up.ordinal()] = new Quad("up", _xExtent * 2, _zExtent * 2);
        _skyboxQuads[Face.Up.ordinal()]
                .setRotation(new Matrix3().fromAngles(Math.toRadians(90), Math.toRadians(270), 0));
        _skyboxQuads[Face.Up.ordinal()].setTranslation(new Vector3(0, _yExtent, 0));
        _skyboxQuads[Face.Down.ordinal()] = new Quad("down", _xExtent * 2, _zExtent * 2);
        _skyboxQuads[Face.Down.ordinal()].setRotation(new Matrix3().fromAngles(Math.toRadians(270),
                Math.toRadians(270), 0));
        _skyboxQuads[Face.Down.ordinal()].setTranslation(new Vector3(0, -_yExtent, 0));

        // We don't want the light to effect our skybox
        getSceneHints().setLightCombineMode(LightCombineMode.Off);

        getSceneHints().setTextureCombineMode(TextureCombineMode.Replace);

        final ZBufferState zbuff = new ZBufferState();
        zbuff.setEnabled(false);
        setRenderState(zbuff);

        final FogState fs = new FogState();
        fs.setEnabled(false);
        setRenderState(fs);

        // We don't want it making our skybox disapear, so force view
        getSceneHints().setCullHint(CullHint.Never);

        for (int i = 0; i < 6; i++) {
            // Make sure texture is only what is set.
            _skyboxQuads[i].getSceneHints().setTextureCombineMode(TextureCombineMode.Replace);

            // Make sure no lighting on the skybox
            _skyboxQuads[i].getSceneHints().setLightCombineMode(LightCombineMode.Off);

            // Make sure the quad is viewable
            _skyboxQuads[i].getSceneHints().setCullHint(CullHint.Never);

            // Add to the prebucket.
            _skyboxQuads[i].getSceneHints().setRenderBucketType(RenderBucketType.PreBucket);

            // And attach the skybox as a child
            attachChild(_skyboxQuads[i]);
        }
    }

    /**
     * Retrieve the quad indicated by the given side.
     *
     * @param face
     *            One of Skybox.Face.North, Skybox.Face.South, and so on...
     * @return The Quad that makes up that side of the Skybox.
     */
    public Quad getFace(final Face face) {
        return _skyboxQuads[face.ordinal()];
    }

    public void preloadTexture(final Face face, final Renderer r) {
        final TextureState ts = (TextureState) _skyboxQuads[face.ordinal()]
                .getLocalRenderState(RenderState.StateType.Texture);
        if (ts != null) {
            r.applyState(StateType.Texture, ts);
        }
    }

    /**
     * Force all of the textures to load. This prevents pauses later during the application as you pan around the world.
     */
    public void preloadTextures(final Renderer r) {
        for (int x = 0; x < 6; x++) {
            final TextureState ts = (TextureState) _skyboxQuads[x].getLocalRenderState(RenderState.StateType.Texture);
            if (ts != null) {
                r.applyState(StateType.Texture, ts);
            }
        }

    }

    @Override
    public void write(final OutputCapsule capsule) throws IOException {
        super.write(capsule);
        capsule.write(_xExtent, "xExtent", 0);
        capsule.write(_yExtent, "yExtent", 0);
        capsule.write(_zExtent, "zExtent", 0);
        capsule.write(_skyboxQuads, "skyboxQuads", null);
    }

    @Override
    public void read(final InputCapsule capsule) throws IOException {
        super.read(capsule);
        _xExtent = capsule.readFloat("xExtent", 0);
        _yExtent = capsule.readFloat("yExtent", 0);
        _zExtent = capsule.readFloat("zExtent", 0);
        _skyboxQuads = CapsuleUtils.asArray(capsule.readSavableArray("skyboxQuads", null), Quad.class);
    }
}
TOP

Related Classes of com.ardor3d.scenegraph.extension.Skybox

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.