WebGL Demos
PHP Data Pivot
PHP Data Subtotals
HTML5 Graph
Java NW3D2
JS Code Formatter
HTML5 Clock
Silverlight Gauge
Java NW3D
Java Fireworks
Java Early 3D
Java Snow
Java Dogfight
Java Water Simulation
Java Bump Mapping
Java Elite Ships

NW3D - Skybox

I've now added a Skybox facility. This was quite a simple modification in that the Skybox is just a large cube with inward facing textured sides. The key difference between the Skybox object and all other objects in the scene is that the Skybox does not translate with the rest of the scene, i.e. does not move relative to the camera. However, it does rotate with the camera. In this way the distance between camera/player and Skybox is pretty much constant (allowing for rotation) and the illusion is of far away scenery within the current world space. As with previous demos, use the cursor keys to move and 'a' to jump. Try climbing to the top of the tower for a better view.

No Java Support.

Within the 'objectfactory' class I've defined a new 'skybox' object type, which requires a dimension and six materials/textures to use for the inward facing sides. The dimension should be a value large enough to place the Skybox beyond other scene objects but still within the far clipping distance.

Skybox object within 'objectfactory'

public static nw3d_object Skybox(double d, nw3d_material front, nw3d_material back, nw3d_material left, nw3d_material right, nw3d_material top, nw3d_material bottom) {
	double hd=d/2;
	nw3d_object obj = new nw3d_object();
	//The cuboid has 24 vertices (non shared)
	obj.addTexVert(-hd, hd,-hd,1,0);
	obj.addTexVert( hd, hd,-hd,0,0);
	obj.addTexVert( hd,-hd,-hd,0,1);
	obj.addTexVert( hd, hd,-hd,1,0);
	obj.addTexVert( hd, hd, hd,0,0);
	obj.addTexVert( hd,-hd, hd,0,1);
	obj.addTexVert( hd,-hd,-hd,1,1);
	obj.addTexVert(-hd, hd, hd,0,0);
	obj.addTexVert( hd, hd, hd,1,0);
	obj.addTexVert( hd,-hd, hd,1,1);
	obj.addTexVert(-hd,-hd, hd,0,1);
	obj.addTexVert(-hd, hd,-hd,0,0);
	obj.addTexVert(-hd, hd, hd,1,0);
	obj.addTexVert(-hd,-hd, hd,1,1);
	obj.addTexVert(-hd, hd, hd,0,1);
	obj.addTexVert( hd, hd, hd,1,1);
	obj.addTexVert( hd, hd,-hd,1,0);
	obj.addTexVert(-hd, hd,-hd,0,0);
	obj.addTexVert(-hd,-hd, hd,0,0);
	obj.addTexVert( hd,-hd, hd,1,0);
	obj.addTexVert( hd,-hd,-hd,1,1);
	//6 sides, 12 triangles, wound clockwise
	obj.addTriMat(2,3,0,1);     //Back
	obj.addTriMat(1,2,0,1);     //Back
	obj.addTriMat(6,7,4,3);     //Right
	obj.addTriMat(5,6,4,3);     //Right
	obj.addTriMat(11,10,9,0);    //Front
	obj.addTriMat(8,11,9,0);     //Front
	obj.addTriMat(15,14,13,2);     //Left
	obj.addTriMat(12,15,13,2);     //Left
	obj.addTriMat(18,19,16,4);     //Top
	obj.addTriMat(17,18,16,4);     //Top
	obj.addTriMat(21,20,23,5);     //Bottom
	obj.addTriMat(22,21,23,5);     //Bottom
	//6 materials
	obj.VertNorms(true);  //shared vertex normals for smooth join
	return obj;

The Skybox object is identified and treat differently by the scene class through addition of the following entries.

  public boolean skyboxUsed;
  public int skyboxObject;

An 'addSkybox' method has also been added.

  public void addSkybox(int d, nw3d_material front, nw3d_material back,
		nw3d_material left, nw3d_material right,
		nw3d_material top, nw3d_material bottom) {
    addObj(nw3d_objectfactory.Skybox(d, front, back, left, right, top, bottom));
    skyboxUsed = true;
    skyboxObject = o.length-1;

Finally, a condition is added to the scene translation method to ensure that the Skybox does not move.

      for (int i = o.length; --i>=0;) {
	      if (!(skyboxUsed && skyboxObject == i))  o[i].Translate(x,y,z);

I'm rendering the Skybox last in order to minimise overdraw and take advantage of an early z-check exit within the render loop. At the moment ensuring that the Skybox is drawn last is simply down to it always being the last object created within the scene, so not ideal.

  scene.addSkybox(400, front, back, left, right, top, bottom);

Despite this, I've recorded a c.30% reduction in frame rate with Skybox enabled, so some further optimisation is needed!

Back to NW3D index