skybox.java
来自「java 3d game jme 工程开发源代码」· Java 代码 · 共 296 行
JAVA
296 行
/*
* Copyright (c) 2003-2009 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme.scene;
import java.io.IOException;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.RenderState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.export.InputCapsule;
import com.jme.util.export.JMEExporter;
import com.jme.util.export.JMEImporter;
import com.jme.util.export.OutputCapsule;
import com.jme.util.export.Savable;
/**
* 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.
*
* @author David Bitkowski
* @author Jack Lindamood (javadoc only)
* @version $Id: Skybox.java,v 1.16 2006/05/12 21:19:22 nca Exp $
*/
public class Skybox extends Node {
private static final long serialVersionUID = 1L;
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(String name, float xExtent, float yExtent, float zExtent) {
super(name);
this.xExtent = xExtent;
this.yExtent = yExtent;
this.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(Face face, 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(Face face, Texture texture, int textureUnit) {
// Validate
if (face == null) {
throw new IllegalArgumentException("Face can not be null.");
}
TextureState ts = (TextureState) skyboxQuads[face.ordinal()].getRenderState(RenderState.StateType.Texture);
if (ts == null) {
ts = DisplaySystem.getDisplaySystem().getRenderer()
.createTextureState();
}
// Initialize the texture state
ts.setTexture(texture, textureUnit);
ts.setEnabled(true);
// Set the texture to the quad
skyboxQuads[face.ordinal()].setRenderState(ts);
return;
}
public Texture getTexture(Face face) {
if (face == null) {
throw new IllegalArgumentException("Face can not be null.");
}
return ((TextureState)skyboxQuads[face.ordinal()].getRenderState(RenderState.StateType.Texture)).getTexture();
}
private void initialize() {
DisplaySystem display = DisplaySystem.getDisplaySystem();
// 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()].setLocalRotation(new Quaternion(new float[] { 0,
(float) Math.toRadians(180), 0 }));
skyboxQuads[Face.North.ordinal()].setLocalTranslation(new Vector3f(0, 0, zExtent));
skyboxQuads[Face.South.ordinal()] = new Quad("south", xExtent * 2, yExtent * 2);
skyboxQuads[Face.South.ordinal()].setLocalTranslation(new Vector3f(0, 0, -zExtent));
skyboxQuads[Face.East.ordinal()] = new Quad("east", zExtent * 2, yExtent * 2);
skyboxQuads[Face.East.ordinal()].setLocalRotation(new Quaternion(new float[] { 0,
(float) Math.toRadians(90), 0 }));
skyboxQuads[Face.East.ordinal()].setLocalTranslation(new Vector3f(-xExtent, 0, 0));
skyboxQuads[Face.West.ordinal()] = new Quad("west", zExtent * 2, yExtent * 2);
skyboxQuads[Face.West.ordinal()].setLocalRotation(new Quaternion(new float[] { 0,
(float) Math.toRadians(270), 0 }));
skyboxQuads[Face.West.ordinal()].setLocalTranslation(new Vector3f(xExtent, 0, 0));
skyboxQuads[Face.Up.ordinal()] = new Quad("up", xExtent * 2, zExtent * 2);
skyboxQuads[Face.Up.ordinal()].setLocalRotation(new Quaternion(new float[] {
(float) Math.toRadians(90), (float) Math.toRadians(270), 0 }));
skyboxQuads[Face.Up.ordinal()].setLocalTranslation(new Vector3f(0, yExtent, 0));
skyboxQuads[Face.Down.ordinal()] = new Quad("down", xExtent * 2, zExtent * 2);
skyboxQuads[Face.Down.ordinal()].setLocalRotation(new Quaternion(new float[] {
(float) Math.toRadians(270), (float) Math.toRadians(270), 0 }));
skyboxQuads[Face.Down.ordinal()].setLocalTranslation(new Vector3f(0, -yExtent, 0));
// We don't want the light to effect our skybox
setLightCombineMode(Spatial.LightCombineMode.Off);
setTextureCombineMode(TextureCombineMode.Replace);
ZBufferState zbuff = display.getRenderer().createZBufferState();
zbuff.setWritable(false);
zbuff.setEnabled(true);
zbuff.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo);
setRenderState(zbuff);
// We don't want it making our skybox disapear, so force view
setCullHint(Spatial.CullHint.Never);
for (int i = 0; i < 6; i++) {
// Make sure texture is only what is set.
skyboxQuads[i].setTextureCombineMode(TextureCombineMode.Replace);
// Make sure no lighting on the skybox
skyboxQuads[i].setLightCombineMode(Spatial.LightCombineMode.Off);
// Make sure the quad is viewable
skyboxQuads[i].setCullHint(Spatial.CullHint.Never);
// Set a bounding volume
skyboxQuads[i].setModelBound(new BoundingBox());
skyboxQuads[i].updateModelBound();
skyboxQuads[i].setRenderQueueMode(Renderer.QUEUE_SKIP);
skyboxQuads[i].setVBOInfo(null);
// 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(Face face) {
return skyboxQuads[face.ordinal()];
}
public void preloadTexture(Face face) {
TextureState ts = (TextureState) skyboxQuads[face.ordinal()].getRenderState(RenderState.StateType.Texture);
if(ts != null) {
ts.apply();
}
}
/**
* Force all of the textures to load. This prevents pauses later during the
* application as you pan around the world.
*/
public void preloadTextures() {
for (int x = 0; x < 6; x++) {
TextureState ts = (TextureState) skyboxQuads[x].getRenderState(RenderState.StateType.Texture);
if (ts != null)
ts.apply();
}
}
public void write(JMEExporter e) throws IOException {
super.write(e);
OutputCapsule capsule = e.getCapsule(this);
capsule.write(xExtent, "xExtent", 0);
capsule.write(yExtent, "yExtent", 0);
capsule.write(zExtent, "zExtent", 0);
capsule.write(skyboxQuads, "skyboxQuads", null);
}
public void read(JMEImporter e) throws IOException {
super.read(e);
InputCapsule capsule = e.getCapsule(this);
xExtent = capsule.readFloat("xExtent", 0);
yExtent = capsule.readFloat("yExtent", 0);
zExtent = capsule.readFloat("zExtent", 0);
Savable[] savs = capsule.readSavableArray("skyboxQuads", null);
if (savs == null) {
skyboxQuads = null;
initialize();
} else {
skyboxQuads = new Quad[savs.length];
for (int x = 0; x < savs.length; x++) {
skyboxQuads[x] = (Quad)savs[x];
}
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?