mirror of
https://github.com/minetest/irrlicht.git
synced 2024-12-26 07:57:30 +01:00
2928a632a4
This breaks compiling. To have old values replace false with EZW_OFF and true with EWZ_AUTO. There's a bit history to this change. ZWriteFineControl got introduced after 1.8 so it was never in a released version. Basically it was needed after some changes had been made to allow shaders to have zwrite enabled independent of the material-type (which worked badly for shaders). This had caused other problems as it was then enabled too often instead. So to quickly fix those bugs and avoid breaking compatibility I had introduced a new enum ZWriteFineControl in SMaterial. This worked and didn't break compiling - but I noticed by now that introducing a second flag for this made maintainance for an already very hard to understand problem (figuring out the implementation of transparency and zwriting) even more complicated. So to keep maintance somewhat sane I decided to break compiling now and merge those two flags. The behavior should not be affected by this commit - except for users which set this flag already in their code and have to switch to the enum now. Serialization is switched on loading old files (so SMaterial has enum already and writes that out). git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6026 dfc29bdd-3216-0410-991c-e03cc46cb475
261 lines
7.7 KiB
C++
261 lines
7.7 KiB
C++
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
|
// This file is part of the "Irrlicht Engine".
|
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
|
|
|
#include "CSkyBoxSceneNode.h"
|
|
#include "IVideoDriver.h"
|
|
#include "ISceneManager.h"
|
|
#include "ICameraSceneNode.h"
|
|
#include "S3DVertex.h"
|
|
#include "os.h"
|
|
|
|
namespace irr
|
|
{
|
|
namespace scene
|
|
{
|
|
|
|
//! constructor
|
|
CSkyBoxSceneNode::CSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, video::ITexture* left,
|
|
video::ITexture* right, video::ITexture* front, video::ITexture* back, ISceneNode* parent, ISceneManager* mgr, s32 id)
|
|
: ISceneNode(parent, mgr, id)
|
|
{
|
|
#ifdef _DEBUG
|
|
setDebugName("CSkyBoxSceneNode");
|
|
#endif
|
|
|
|
setAutomaticCulling(scene::EAC_OFF);
|
|
Box.MaxEdge.set(0,0,0);
|
|
Box.MinEdge.set(0,0,0);
|
|
|
|
// create indices
|
|
|
|
Indices[0] = 0;
|
|
Indices[1] = 1;
|
|
Indices[2] = 2;
|
|
Indices[3] = 3;
|
|
|
|
// create material
|
|
|
|
video::SMaterial mat;
|
|
mat.Lighting = false;
|
|
mat.ZBuffer = video::ECFN_DISABLED;
|
|
mat.ZWriteEnable = video::EZW_OFF;
|
|
mat.AntiAliasing=0;
|
|
mat.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
|
|
mat.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
|
|
mat.TextureLayer[0].TextureWrapW = video::ETC_CLAMP_TO_EDGE;
|
|
|
|
/* Hey, I am no artist, but look at that
|
|
cool ASCII art I made! ;)
|
|
|
|
-111 111
|
|
/6--------/5 y
|
|
/ | / | ^ z
|
|
/ | 11-1 | | /
|
|
-11-1 3---------2 | |/
|
|
| 7- - -| -4 1-11 *---->x
|
|
| -1-11 | / 3-------|2
|
|
|/ | / | //|
|
|
0---------1/ | // |
|
|
-1-1-1 1-1-1 |// |
|
|
0--------1
|
|
*/
|
|
|
|
video::ITexture* tex = front;
|
|
if (!tex) tex = left;
|
|
if (!tex) tex = back;
|
|
if (!tex) tex = right;
|
|
if (!tex) tex = top;
|
|
if (!tex) tex = bottom;
|
|
|
|
const f32 onepixel = tex?(1.0f / (tex->getSize().Width * 1.5f)) : 0.0f;
|
|
const f32 t = 1.0f - onepixel;
|
|
const f32 o = 0.0f + onepixel;
|
|
|
|
// create front side
|
|
|
|
Material[0] = mat;
|
|
Material[0].setTexture(0, front);
|
|
Vertices[0] = video::S3DVertex(-1,-1,-1, 0,0,1, video::SColor(255,255,255,255), t, t);
|
|
Vertices[1] = video::S3DVertex( 1,-1,-1, 0,0,1, video::SColor(255,255,255,255), o, t);
|
|
Vertices[2] = video::S3DVertex( 1, 1,-1, 0,0,1, video::SColor(255,255,255,255), o, o);
|
|
Vertices[3] = video::S3DVertex(-1, 1,-1, 0,0,1, video::SColor(255,255,255,255), t, o);
|
|
|
|
// create left side
|
|
|
|
Material[1] = mat;
|
|
Material[1].setTexture(0, left);
|
|
Vertices[4] = video::S3DVertex( 1,-1,-1, -1,0,0, video::SColor(255,255,255,255), t, t);
|
|
Vertices[5] = video::S3DVertex( 1,-1, 1, -1,0,0, video::SColor(255,255,255,255), o, t);
|
|
Vertices[6] = video::S3DVertex( 1, 1, 1, -1,0,0, video::SColor(255,255,255,255), o, o);
|
|
Vertices[7] = video::S3DVertex( 1, 1,-1, -1,0,0, video::SColor(255,255,255,255), t, o);
|
|
|
|
// create back side
|
|
|
|
Material[2] = mat;
|
|
Material[2].setTexture(0, back);
|
|
Vertices[8] = video::S3DVertex( 1,-1, 1, 0,0,-1, video::SColor(255,255,255,255), t, t);
|
|
Vertices[9] = video::S3DVertex(-1,-1, 1, 0,0,-1, video::SColor(255,255,255,255), o, t);
|
|
Vertices[10] = video::S3DVertex(-1, 1, 1, 0,0,-1, video::SColor(255,255,255,255), o, o);
|
|
Vertices[11] = video::S3DVertex( 1, 1, 1, 0,0,-1, video::SColor(255,255,255,255), t, o);
|
|
|
|
// create right side
|
|
|
|
Material[3] = mat;
|
|
Material[3].setTexture(0, right);
|
|
Vertices[12] = video::S3DVertex(-1,-1, 1, 1,0,0, video::SColor(255,255,255,255), t, t);
|
|
Vertices[13] = video::S3DVertex(-1,-1,-1, 1,0,0, video::SColor(255,255,255,255), o, t);
|
|
Vertices[14] = video::S3DVertex(-1, 1,-1, 1,0,0, video::SColor(255,255,255,255), o, o);
|
|
Vertices[15] = video::S3DVertex(-1, 1, 1, 1,0,0, video::SColor(255,255,255,255), t, o);
|
|
|
|
// create top side
|
|
|
|
Material[4] = mat;
|
|
Material[4].setTexture(0, top);
|
|
Vertices[16] = video::S3DVertex( 1, 1,-1, 0,-1,0, video::SColor(255,255,255,255), t, t);
|
|
Vertices[17] = video::S3DVertex( 1, 1, 1, 0,-1,0, video::SColor(255,255,255,255), o, t);
|
|
Vertices[18] = video::S3DVertex(-1, 1, 1, 0,-1,0, video::SColor(255,255,255,255), o, o);
|
|
Vertices[19] = video::S3DVertex(-1, 1,-1, 0,-1,0, video::SColor(255,255,255,255), t, o);
|
|
|
|
// create bottom side
|
|
|
|
Material[5] = mat;
|
|
Material[5].setTexture(0, bottom);
|
|
Vertices[20] = video::S3DVertex( 1,-1, 1, 0,1,0, video::SColor(255,255,255,255), o, o);
|
|
Vertices[21] = video::S3DVertex( 1,-1,-1, 0,1,0, video::SColor(255,255,255,255), t, o);
|
|
Vertices[22] = video::S3DVertex(-1,-1,-1, 0,1,0, video::SColor(255,255,255,255), t, t);
|
|
Vertices[23] = video::S3DVertex(-1,-1, 1, 0,1,0, video::SColor(255,255,255,255), o, t);
|
|
}
|
|
|
|
|
|
//! renders the node.
|
|
void CSkyBoxSceneNode::render()
|
|
{
|
|
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
|
scene::ICameraSceneNode* camera = SceneManager->getActiveCamera();
|
|
|
|
if (!camera || !driver)
|
|
return;
|
|
|
|
if ( !camera->isOrthogonal() )
|
|
{
|
|
// draw perspective skybox
|
|
|
|
core::matrix4 translate(AbsoluteTransformation);
|
|
translate.setTranslation(camera->getAbsolutePosition());
|
|
|
|
// Draw the sky box between the near and far clip plane
|
|
const f32 viewDistance = (camera->getNearValue() + camera->getFarValue()) * 0.5f;
|
|
core::matrix4 scale;
|
|
scale.setScale(core::vector3df(viewDistance, viewDistance, viewDistance));
|
|
|
|
driver->setTransform(video::ETS_WORLD, translate * scale);
|
|
|
|
for (s32 i=0; i<6; ++i)
|
|
{
|
|
driver->setMaterial(Material[i]);
|
|
driver->drawIndexedTriangleFan(&Vertices[i*4], 4, Indices, 2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// draw orthogonal skybox,
|
|
// simply choose one texture and draw it as 2d picture.
|
|
// there could be better ways to do this, but currently I think this is ok.
|
|
|
|
core::vector3df lookVect = camera->getTarget() - camera->getAbsolutePosition();
|
|
lookVect.normalize();
|
|
core::vector3df absVect( core::abs_(lookVect.X),
|
|
core::abs_(lookVect.Y),
|
|
core::abs_(lookVect.Z));
|
|
|
|
int idx = 0;
|
|
|
|
if ( absVect.X >= absVect.Y && absVect.X >= absVect.Z )
|
|
{
|
|
// x direction
|
|
idx = lookVect.X > 0 ? 0 : 2;
|
|
}
|
|
else
|
|
if ( absVect.Y >= absVect.X && absVect.Y >= absVect.Z )
|
|
{
|
|
// y direction
|
|
idx = lookVect.Y > 0 ? 4 : 5;
|
|
}
|
|
else
|
|
if ( absVect.Z >= absVect.X && absVect.Z >= absVect.Y )
|
|
{
|
|
// z direction
|
|
idx = lookVect.Z > 0 ? 1 : 3;
|
|
}
|
|
|
|
video::ITexture* tex = Material[idx].getTexture(0);
|
|
|
|
if ( tex )
|
|
{
|
|
core::rect<s32> rctDest(core::position2d<s32>(-1,0),
|
|
core::dimension2di(driver->getCurrentRenderTargetSize()));
|
|
core::rect<s32> rctSrc(core::position2d<s32>(0,0),
|
|
core::dimension2di(tex->getOriginalSize()));
|
|
|
|
driver->draw2DImage(tex, rctDest, rctSrc);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//! returns the axis aligned bounding box of this node
|
|
const core::aabbox3d<f32>& CSkyBoxSceneNode::getBoundingBox() const
|
|
{
|
|
return Box;
|
|
}
|
|
|
|
|
|
void CSkyBoxSceneNode::OnRegisterSceneNode()
|
|
{
|
|
if (IsVisible)
|
|
SceneManager->registerNodeForRendering(this, ESNRP_SKY_BOX);
|
|
|
|
ISceneNode::OnRegisterSceneNode();
|
|
}
|
|
|
|
|
|
//! returns the material based on the zero based index i.
|
|
video::SMaterial& CSkyBoxSceneNode::getMaterial(u32 i)
|
|
{
|
|
return Material[i];
|
|
}
|
|
|
|
|
|
//! returns amount of materials used by this scene node.
|
|
u32 CSkyBoxSceneNode::getMaterialCount() const
|
|
{
|
|
return 6;
|
|
}
|
|
|
|
|
|
//! Creates a clone of this scene node and its children.
|
|
ISceneNode* CSkyBoxSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
|
{
|
|
if (!newParent) newParent = Parent;
|
|
if (!newManager) newManager = SceneManager;
|
|
|
|
CSkyBoxSceneNode* nb = new CSkyBoxSceneNode(0,0,0,0,0,0, newParent,
|
|
newManager, ID);
|
|
|
|
nb->cloneMembers(this, newManager);
|
|
|
|
for (u32 i=0; i<6; ++i)
|
|
nb->Material[i] = Material[i];
|
|
|
|
if ( newParent )
|
|
nb->drop();
|
|
return nb;
|
|
}
|
|
|
|
|
|
} // end namespace scene
|
|
} // end namespace irr
|
|
|