(C++) SkyDome instead of SkyBox

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
alc
Posts: 31
Joined: Sun Jun 25, 2006 10:59 pm
Location: Denmark

(C++) SkyDome instead of SkyBox

Post by alc »

Updated Oct 5 2006:
The skydome function below is now part of Irrlicht 1.1 and obviously the subsequent SVN updates. Thus, use this instead of the code below. Sry about the missing pictures, but I do clean my http drive occasionally.

---------------

I've made a sky dome construction similar to the sky box for my current project. I think it looks better than the sky box (it does not have the box-look that you tend to get with skybox), and you can use those really nice 360 degrees panorama shots available on the net.

So, guess what, I though I'd share it :o

It is based on the sky box code in the engine; I've simply replaced the box mesh with a dome mesh based on standard spherical coordinates.

To ease the use, here's a step-by-step list to implement it in your project (you can also add it to the engine if you want to, however, I prefer to have it separately for when the engine is upgraded).

1) Add the following code in one of you header files:

Code: Select all

class CSkyDomeSceneNode : public ISceneNode
{
  public:
	 CSkyDomeSceneNode(video::ITexture*, int, int, double, double, ISceneNode*, ISceneManager*, s32);
	 virtual ~CSkyDomeSceneNode();
	 virtual void OnPreRender();
	 virtual void render();
	 virtual const core::aabbox3d<f32>& getBoundingBox() const;
	 virtual video::SMaterial& getMaterial(s32 i);
	 virtual s32 getMaterialCount();
	 virtual ESCENE_NODE_TYPE getType() { return ESNT_SKY_BOX; }

  private:
    core::aabbox3d<f32> Box;
    u16 *Indices;
    video::S3DVertex *Vertices;
    video::SMaterial Material;
    u16 NumOfVertices;
    u16 NumOfFaces;
};
2) Then add the following code to a c-file

Code: Select all

/* hori_res and vert_res:
   Controls the number of faces along the horizontal axis (30 is a good value)
   and the number of faces along the vertical axis (8 is a good value).

   image_percentage:
   Only the top image_percentage of the image is used, e.g. 0.8 uses the top 80% of the image,
   1.0 uses the entire image. This is useful as some landscape images have a small banner 
   at the bottom that you don't want.

   half_sphere_fraction:
   This controls how far around the sphere the sky dome goes. For value 1.0 you get exactly the upper 
   hemisphere, for 1.1 you get slightly more, and for 2.0 you get a full sphere. It is sometimes useful
   to use a value slightly bigger than 1 to avoid a gap between some ground place and the sky. This
   parameters stretches the image to fit the chosen "sphere-size". */

CSkyDomeSceneNode::CSkyDomeSceneNode(video::ITexture* sky, int hori_res, int vert_res, 
      double image_percentage, double half_sphere_fraction, ISceneNode* parent, ISceneManager* mgr, s32 id)
      : ISceneNode(parent, mgr, id)
{
  double radius = 1000;               /* Adjust this to get more or less perspective distorsion. */
  double azimuth, azimuth_step; 
  double elevation, elevation_step;
  int k, j, c;

  S3DVertex vtx;

  AutomaticCullingEnabled = false;
  Material.Lighting = false;
  Material.ZBuffer = false;
  Material.ZWriteEnable = false;
  Material.BilinearFilter = true;
  Material.Texture1 = sky;

  azimuth_step = 2.*pi/(double)hori_res;
  elevation_step = half_sphere_fraction*pi/2./(double)vert_res;

  NumOfVertices = (hori_res+1)*(vert_res+1);
  NumOfFaces = (2*vert_res-1)*hori_res;

  Vertices = new S3DVertex[NumOfVertices];
  Indices = new u16[3*NumOfFaces]; 

 	vtx.Color.set(255,255,255,255);
	vtx.Normal.set(0,0,0);

  c = 0;
  for (k = 0, azimuth = 0; k <= hori_res; k++, azimuth += azimuth_step)
  {
    for (j = 0, elevation = pi/2.; j <= vert_res; j++, elevation -= elevation_step)
    {
      vtx.Pos.set(radius*cos(elevation)*sin(azimuth),radius*sin(elevation)+50,radius*cos(elevation)*cos(azimuth));
      vtx.TCoords.set((f32)k/(f32)hori_res, (f32)j/(f32)vert_res*image_percentage);
		  Vertices[c++] = vtx;
    }
  }

  c = 0;
  for (k = 0; k < hori_res; k++) 
  {
    Indices[c++] = vert_res+2+(vert_res+1)*k;
    Indices[c++] = 1+(vert_res+1)*k;
    Indices[c++] = 0+(vert_res+1)*k;

    for (j = 1; j < vert_res; j++)
    {
      Indices[c++] = vert_res+2+(vert_res+1)*k+j;
      Indices[c++] = 1+(vert_res+1)*k+j;
      Indices[c++] = 0+(vert_res+1)*k+j;

      Indices[c++] = vert_res+1+(vert_res+1)*k+j;
      Indices[c++] = vert_res+2+(vert_res+1)*k+j;
      Indices[c++] = 0+(vert_res+1)*k+j;
    }
  }
}


//! destructor
CSkyDomeSceneNode::~CSkyDomeSceneNode()
{
}


//! renders the node.
void CSkyDomeSceneNode::render()
{
	video::IVideoDriver* driver = SceneManager->getVideoDriver();
	scene::ICameraSceneNode* camera = SceneManager->getActiveCamera();

	if (!camera || !driver)
		return;

	if ( !camera->isOrthogonal() )
	{
		core::matrix4 mat;
		mat.setTranslation(camera->getAbsolutePosition());

		driver->setTransform(video::ETS_WORLD, mat);
		
  	driver->setMaterial(Material);
		driver->drawIndexedTriangleList(Vertices, NumOfVertices, Indices, NumOfFaces);
	}
}

//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CSkyDomeSceneNode::getBoundingBox() const
{
	return Box;
}


void CSkyDomeSceneNode::OnPreRender()
{
	if (IsVisible)
		SceneManager->registerNodeForRendering(this, ESNRP_SKY_BOX);

	ISceneNode::OnPreRender();
}


//! returns the material based on the zero based index i. To get the amount
//! of materials used by this scene node, use getMaterialCount().
//! This function is needed for inserting the node into the scene hirachy on a
//! optimal position for minimizing renderstate changes, but can also be used
//! to directly modify the material of a scene node.
video::SMaterial& CSkyDomeSceneNode::getMaterial(s32 i)
{
  return Material;
}


//! returns amount of materials used by this scene node.
s32 CSkyDomeSceneNode::getMaterialCount()
{
	return 1;
}
3) You insert the dome into a scene by

Code: Select all

	ISceneNode* node = new CSkyDomeSceneNode(driver->getTexture("filename"),30,8,0.96f,2.f,smgr->getRootSceneNode(),smgr,0);
	node->drop();
4) You should now have a good looking world around you scene (provided that you find a nice panorama view).

Note that the dome uses a triangular mesh (doh!) and that all faces in the dome are actualy made up of squares from two triangles, except for the the top-most part of the dome, which is constructed directly from triangles. This gives a nice look at zenith. This feature is not implemented at the bottom of the sphere (as I figured that this is not so often used), so you MIGHT get a slightly off-looking pattern a the very bottom.

Note also that as skybox this is implemented as a static mesh that always renders around your current camera position (this gives an impression of the box/dome not moving). Consequently, you cannot shift the horizon down by moving the scene upwards in order to hide any potential gap between your ground and the bottom end of the sky image. Instead, you should use the half_sphere_fraction value in the constructor to adjust this.

Here are a couple of examples (I through in a helicopter from my project to add at least some other than just the dome):

This first one is a galactic thing using this

Image

as panorama view. This gives you your well-known "helicopter leaving the galaxy" kind of look.

Image

This second screen shot of the same scene is directly towards the top of the dome to show that it looks quite nice.

Image


The second example is more earthlike. This is used as panorama:

Image

Notice how the not so circular rings around the sun becomes circular in the screen shot (well, almost, but the distorsion comes from the perspective mapping in Irrlicht, not from the dome itself).

Image


Then I found this scenery somewhere on the net

Image

and you get this sky dome look

Image


This last example is my favorite:

Image

which gives a scene looking like this (notice how the banner at the bottom is not visible, see the explanation above).

Image

and looking directly to the top

Image

Notice that the panorama views above are all found somewhere on the net, and are only small versions of the original used here to illustrate the sky dome technique. Obviously, you should get the originals to get a proper resolution. A good place to start is

http://lfgrafix.com/grafix/3dSkyInMot/SIMdex.html

or google for 'panorama 360 sky' or similar.

Have fun with it.
Last edited by alc on Thu Oct 05, 2006 11:20 pm, edited 1 time in total.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Looks pretty good. Finally someone who did this often requested task and also a very goo code quality (Yay for the coomputer scientists :D )
CZestmyr
Posts: 72
Joined: Sat Feb 12, 2005 7:11 pm
Location: Czech Republic
Contact:

Skoboxes rule

Post by CZestmyr »

I dont'ŧ think that skyboxes are so bad. And they definitely don't have to look 'cubeish'. If you render the skybox textures as planar projections of a 3D scene on the walls of the cube, you end up with 6 textures that are distorted on the edges, due to the projection. But when applied to the skybox, this distortion is essential for the skybox in order not to look like a skybox ( :P ! ).

So you can model your skydome in a 3D modeling program and then render your skybox textures in it. The outcome doesn't look bad at all.
Bugfree is not a synonym to dumbass-resistant

My irrlicht files and tutorials
My music in mp3
alc
Posts: 31
Joined: Sun Jun 25, 2006 10:59 pm
Location: Denmark

Re: Skoboxes rule

Post by alc »

CZestmyr wrote:[snip]

So you can model your skydome in a 3D modeling program and then render your skybox textures in it. The outcome doesn't look bad at all.
czsetmyr, I do agree that you can get some nice skyboxes that way. However, I wanted to use the 360 views without bothering to remake it for at sky box ...
alc
Posts: 31
Joined: Sun Jun 25, 2006 10:59 pm
Location: Denmark

Post by alc »

hybrid wrote:Looks pretty good. Finally someone who did this often requested task and also a very goo code quality (Yay for the coomputer scientists :D )
Thx, hybrid.
I'm a mathematician, though, and they have this thing about being confused with computer scientists :wink:
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You're a professor for mathematics, doing autonomous helicopter experiments, that can program not just Fortran :shock: That's pretty strange :wink: (Ok, most mathematicians can program Mathematica :lol: )
RapchikProgrammer
Posts: 279
Joined: Fri Dec 24, 2004 6:37 pm

Post by RapchikProgrammer »

Thanx a lot for that bro! I was thinking of making that ma self!
anoki
Posts: 58
Joined: Fri May 05, 2006 8:31 am

Post by anoki »

Hey thats a really good idea to make a skydome.
Sometimes it is much better then the boxes.
Thanks a lot for the code.
I will try it !
anoki
Posts: 58
Joined: Fri May 05, 2006 8:31 am

Post by anoki »

Hello,
do you have maybe a complete vs project source ?
Would be a great help and save me a lot time for trying because
i am new to c++ .

Thanx

anoki
alc
Posts: 31
Joined: Sun Jun 25, 2006 10:59 pm
Location: Denmark

Post by alc »

anoki wrote:Hello,
do you have maybe a complete vs project source ?
Would be a great help and save me a lot time for trying because
i am new to c++ .
The above code is all there is and the four steps tell you all there is to it (the driver and smgr in step 3 are exactly as shown in all the irrlicht tutorials). If you cannot make that work, I suggest starting with a C++ tut :wink: (there is a really good one at www.cplusplus.com)
anoki
Posts: 58
Joined: Fri May 05, 2006 8:31 am

Post by anoki »

Hello Alc,

thanx ! I will try to get it running.
Like i said i am still new to c++.

Bye Anoki
Halan
Posts: 447
Joined: Tue Oct 04, 2005 8:17 pm
Location: Germany, Freak City
Contact:

Post by Halan »

mm theres a little bug if i use directx 9. the texture doesnt really fit so theres a grey line :(
irkab1rka
Posts: 9
Joined: Sat Jul 09, 2005 8:06 pm

Forum management.

Post by irkab1rka »

I'm not sure if this code is in Irrlicht 1.0
but it should been there.
and then this topic should have been moved to the history folder.

btw the code should not assume u always have the namespaces used like:
using namespace irr;
using namespace irr::scene;
using namespace irr::video;
Those are mandatory to use this skydome. Anyway, it works.
Mikenoworth
Posts: 78
Joined: Sat May 27, 2006 9:24 pm
Location: Logan, UT

Post by Mikenoworth »

Code: Select all

//! destructor 
CSkyDomeNode::~CSkyDomeNode() 
{ 	
	delete (Vertices);
	delete (Indices);
} 
I think you forgot that.
Stout Beer
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The two errors reported last are not in the version now being part of Irrlicht core, so you might want to give Irrlicht SVN a try.
Post Reply