source: trunk/ardor3d-core/src/main/java/com/ardor3d/scenegraph/extension/Skybox.java @ 1805

Revision 1805, 9.4 KB checked in by ardorlabs, 3 months ago (diff)

API cleanup suggestion from forum user "larza":

  • standardization of model loader scene access methods.
  • standardization of constructor param order for lwjgl canvas types.

Also, lots of various code warnings cleanup.

  • Property svn:executable set to *
Line 
1/**
2 * Copyright (c) 2008-2011 Ardor Labs, Inc.
3 *
4 * This file is part of Ardor3D.
5 *
6 * Ardor3D is free software: you can redistribute it and/or modify it
7 * under the terms of its license which may be found in the accompanying
8 * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
9 */
10
11package com.ardor3d.scenegraph.extension;
12
13import java.io.IOException;
14
15import com.ardor3d.image.Texture;
16import com.ardor3d.image.Texture.WrapMode;
17import com.ardor3d.math.Matrix3;
18import com.ardor3d.math.Vector3;
19import com.ardor3d.renderer.Renderer;
20import com.ardor3d.renderer.queue.RenderBucketType;
21import com.ardor3d.renderer.state.FogState;
22import com.ardor3d.renderer.state.RenderState;
23import com.ardor3d.renderer.state.RenderState.StateType;
24import com.ardor3d.renderer.state.TextureState;
25import com.ardor3d.renderer.state.ZBufferState;
26import com.ardor3d.scenegraph.Node;
27import com.ardor3d.scenegraph.hint.CullHint;
28import com.ardor3d.scenegraph.hint.LightCombineMode;
29import com.ardor3d.scenegraph.hint.TextureCombineMode;
30import com.ardor3d.scenegraph.shape.Quad;
31import com.ardor3d.util.export.CapsuleUtils;
32import com.ardor3d.util.export.InputCapsule;
33import com.ardor3d.util.export.OutputCapsule;
34
35/**
36 * A Box made of textured quads that simulate having a sky, horizon and so forth around your scene. Either attach to a
37 * camera node or update on each frame to set this skybox at the camera's position.
38 */
39public class Skybox extends Node {
40
41    public enum Face {
42        /** The +Z side of the skybox. */
43        North,
44        /** The -Z side of the skybox. */
45        South,
46        /** The -X side of the skybox. */
47        East,
48        /** The +X side of the skybox. */
49        West,
50        /** The +Y side of the skybox. */
51        Up,
52        /** The -Y side of the skybox. */
53        Down;
54    }
55
56    private float _xExtent;
57    private float _yExtent;
58    private float _zExtent;
59
60    private Quad[] _skyboxQuads;
61
62    public Skybox() {}
63
64    /**
65     * Creates a new skybox. The size of the skybox and name is specified here. By default, no textures are set.
66     *
67     * @param name
68     *            The name of the skybox.
69     * @param xExtent
70     *            The x size of the skybox in both directions from the center.
71     * @param yExtent
72     *            The y size of the skybox in both directions from the center.
73     * @param zExtent
74     *            The z size of the skybox in both directions from the center.
75     */
76    public Skybox(final String name, final float xExtent, final float yExtent, final float zExtent) {
77        super(name);
78
79        _xExtent = xExtent;
80        _yExtent = yExtent;
81        _zExtent = zExtent;
82
83        initialize();
84    }
85
86    /**
87     * Set the texture to be displayed on the given face of the skybox. Replaces any existing texture on that face.
88     *
89     * @param face
90     *            the face to set
91     * @param texture
92     *            The texture for that side to assume.
93     * @throws IllegalArgumentException
94     *             if face is null.
95     */
96    public void setTexture(final Face face, final Texture texture) {
97        if (face == null) {
98            throw new IllegalArgumentException("Face can not be null.");
99        }
100
101        _skyboxQuads[face.ordinal()].clearRenderState(RenderState.StateType.Texture);
102        setTexture(face, texture, 0);
103    }
104
105    /**
106     * Set the texture to be displayed on the given side of the skybox. Only replaces the texture at the index specified
107     * by textureUnit.
108     *
109     * @param face
110     *            the face to set
111     * @param texture
112     *            The texture for that side to assume.
113     * @param textureUnit
114     *            The texture unite of the given side's TextureState the texture will assume.
115     */
116    public void setTexture(final Face face, final Texture texture, final int textureUnit) {
117        // Validate
118        if (face == null) {
119            throw new IllegalArgumentException("Face can not be null.");
120        }
121
122        TextureState ts = (TextureState) _skyboxQuads[face.ordinal()]
123                .getLocalRenderState(RenderState.StateType.Texture);
124        if (ts == null) {
125            ts = new TextureState();
126        }
127
128        // Initialize the texture state
129        ts.setTexture(texture, textureUnit);
130        ts.setEnabled(true);
131
132        texture.setWrap(WrapMode.EdgeClamp);
133
134        // Set the texture to the quad
135        _skyboxQuads[face.ordinal()].setRenderState(ts);
136
137        return;
138    }
139
140    public Texture getTexture(final Face face) {
141        if (face == null) {
142            throw new IllegalArgumentException("Face can not be null.");
143        }
144        return ((TextureState) _skyboxQuads[face.ordinal()].getLocalRenderState(RenderState.StateType.Texture))
145                .getTexture();
146    }
147
148    public void initialize() {
149
150        // Skybox consists of 6 sides
151        _skyboxQuads = new Quad[6];
152
153        // Create each of the quads
154        _skyboxQuads[Face.North.ordinal()] = new Quad("north", _xExtent * 2, _yExtent * 2);
155        _skyboxQuads[Face.North.ordinal()].setRotation(new Matrix3().fromAngles(0, Math.toRadians(180), 0));
156        _skyboxQuads[Face.North.ordinal()].setTranslation(new Vector3(0, 0, _zExtent));
157        _skyboxQuads[Face.South.ordinal()] = new Quad("south", _xExtent * 2, _yExtent * 2);
158        _skyboxQuads[Face.South.ordinal()].setTranslation(new Vector3(0, 0, -_zExtent));
159        _skyboxQuads[Face.East.ordinal()] = new Quad("east", _zExtent * 2, _yExtent * 2);
160        _skyboxQuads[Face.East.ordinal()].setRotation(new Matrix3().fromAngles(0, Math.toRadians(90), 0));
161        _skyboxQuads[Face.East.ordinal()].setTranslation(new Vector3(-_xExtent, 0, 0));
162        _skyboxQuads[Face.West.ordinal()] = new Quad("west", _zExtent * 2, _yExtent * 2);
163        _skyboxQuads[Face.West.ordinal()].setRotation(new Matrix3().fromAngles(0, Math.toRadians(270), 0));
164        _skyboxQuads[Face.West.ordinal()].setTranslation(new Vector3(_xExtent, 0, 0));
165        _skyboxQuads[Face.Up.ordinal()] = new Quad("up", _xExtent * 2, _zExtent * 2);
166        _skyboxQuads[Face.Up.ordinal()]
167                .setRotation(new Matrix3().fromAngles(Math.toRadians(90), Math.toRadians(270), 0));
168        _skyboxQuads[Face.Up.ordinal()].setTranslation(new Vector3(0, _yExtent, 0));
169        _skyboxQuads[Face.Down.ordinal()] = new Quad("down", _xExtent * 2, _zExtent * 2);
170        _skyboxQuads[Face.Down.ordinal()].setRotation(new Matrix3().fromAngles(Math.toRadians(270),
171                Math.toRadians(270), 0));
172        _skyboxQuads[Face.Down.ordinal()].setTranslation(new Vector3(0, -_yExtent, 0));
173
174        // We don't want the light to effect our skybox
175        getSceneHints().setLightCombineMode(LightCombineMode.Off);
176
177        getSceneHints().setTextureCombineMode(TextureCombineMode.Replace);
178
179        final ZBufferState zbuff = new ZBufferState();
180        zbuff.setEnabled(false);
181        setRenderState(zbuff);
182
183        final FogState fs = new FogState();
184        fs.setEnabled(false);
185        setRenderState(fs);
186
187        // We don't want it making our skybox disapear, so force view
188        getSceneHints().setCullHint(CullHint.Never);
189
190        for (int i = 0; i < 6; i++) {
191            // Make sure texture is only what is set.
192            _skyboxQuads[i].getSceneHints().setTextureCombineMode(TextureCombineMode.Replace);
193
194            // Make sure no lighting on the skybox
195            _skyboxQuads[i].getSceneHints().setLightCombineMode(LightCombineMode.Off);
196
197            // Make sure the quad is viewable
198            _skyboxQuads[i].getSceneHints().setCullHint(CullHint.Never);
199
200            // Add to the prebucket.
201            _skyboxQuads[i].getSceneHints().setRenderBucketType(RenderBucketType.PreBucket);
202
203            // And attach the skybox as a child
204            attachChild(_skyboxQuads[i]);
205        }
206    }
207
208    /**
209     * Retrieve the quad indicated by the given side.
210     *
211     * @param face
212     *            One of Skybox.Face.North, Skybox.Face.South, and so on...
213     * @return The Quad that makes up that side of the Skybox.
214     */
215    public Quad getFace(final Face face) {
216        return _skyboxQuads[face.ordinal()];
217    }
218
219    public void preloadTexture(final Face face, final Renderer r) {
220        final TextureState ts = (TextureState) _skyboxQuads[face.ordinal()]
221                .getLocalRenderState(RenderState.StateType.Texture);
222        if (ts != null) {
223            r.applyState(StateType.Texture, ts);
224        }
225    }
226
227    /**
228     * Force all of the textures to load. This prevents pauses later during the application as you pan around the world.
229     */
230    public void preloadTextures(final Renderer r) {
231        for (int x = 0; x < 6; x++) {
232            final TextureState ts = (TextureState) _skyboxQuads[x].getLocalRenderState(RenderState.StateType.Texture);
233            if (ts != null) {
234                r.applyState(StateType.Texture, ts);
235            }
236        }
237
238    }
239
240    @Override
241    public void write(final OutputCapsule capsule) throws IOException {
242        super.write(capsule);
243        capsule.write(_xExtent, "xExtent", 0);
244        capsule.write(_yExtent, "yExtent", 0);
245        capsule.write(_zExtent, "zExtent", 0);
246        capsule.write(_skyboxQuads, "skyboxQuads", null);
247    }
248
249    @Override
250    public void read(final InputCapsule capsule) throws IOException {
251        super.read(capsule);
252        _xExtent = capsule.readFloat("xExtent", 0);
253        _yExtent = capsule.readFloat("yExtent", 0);
254        _zExtent = capsule.readFloat("zExtent", 0);
255        _skyboxQuads = CapsuleUtils.asArray(capsule.readSavableArray("skyboxQuads", null), Quad.class);
256    }
257}
Note: See TracBrowser for help on using the repository browser.