Add alternavive BoundingBox calculation for BillboardSceneNode which can take in a camera node. Thx @Seven and @JacKDuRdEn for bugreports.
There are still some problems (and even bugs) with all this, but fixing those will take more time. I documented some of the problems in code. Also switched to using a MeshBuffer in the billboard (mainly because it's nicer for the emscripten port). git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@5452 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
8990dbcf28
commit
966712c571
|
@ -1,6 +1,7 @@
|
|||
--------------------------
|
||||
Changes in 1.9 (not yet released)
|
||||
|
||||
- Add alternavive BoundingBox calculation for BillboardSceneNode which can take in a camera node. Thx @Seven and @JacKDuRdEn for bugreports.
|
||||
- FPS camera now supports keyboard rotation.
|
||||
- Base FPS-camera movement on last position of mouse instead of always center (works better on platforms where cursor-placement is not allowed)
|
||||
- Octrees with other vertex types than EVT_2TCOORDS can now also use VBO's.
|
||||
|
|
|
@ -120,14 +120,16 @@ namespace scene
|
|||
/** should be called if the mesh changed. */
|
||||
virtual void recalculateBoundingBox()
|
||||
{
|
||||
if (Vertices.empty())
|
||||
BoundingBox.reset(0,0,0);
|
||||
else
|
||||
if (!Vertices.empty())
|
||||
{
|
||||
BoundingBox.reset(Vertices[0].Pos);
|
||||
for (u32 i=1; i<Vertices.size(); ++i)
|
||||
const irr::u32 vsize = Vertices.size();
|
||||
for (u32 i=1; i<vsize; ++i)
|
||||
BoundingBox.addInternalPoint(Vertices[i].Pos);
|
||||
}
|
||||
else
|
||||
BoundingBox.reset(0,0,0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace irr
|
|||
{
|
||||
namespace scene
|
||||
{
|
||||
class ICameraSceneNode;
|
||||
|
||||
//! A billboard scene node.
|
||||
/** A billboard is like a 3d sprite: A 2d element,
|
||||
|
@ -65,6 +66,14 @@ public:
|
|||
\param[out] bottomColor Stores the color of the bottom vertices */
|
||||
virtual void getColor(video::SColor& topColor,
|
||||
video::SColor& bottomColor) const = 0;
|
||||
|
||||
//! Get the real boundingbox used by the billboard, which can depend on the active camera.
|
||||
/** The boundingbox returned will use absolute coordinates.
|
||||
The billboard orients itself toward the camera and some only update in render().
|
||||
So we don't know the real boundingboxes before that. Which would be too late for culling.
|
||||
That is why the usual getBoundingBox will return a "safe" boundingbox which is guaranteed
|
||||
to contain the billboard. While this function can return the real one. */
|
||||
virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) = 0;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
|
|
|
@ -18,6 +18,7 @@ CBillboardSceneNode::CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr,
|
|||
const core::vector3df& position, const core::dimension2d<f32>& size,
|
||||
video::SColor colorTop, video::SColor colorBottom)
|
||||
: IBillboardSceneNode(parent, mgr, id, position)
|
||||
, Buffer(new SMeshBuffer())
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBillboardSceneNode");
|
||||
|
@ -25,26 +26,33 @@ CBillboardSceneNode::CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr,
|
|||
|
||||
setSize(size);
|
||||
|
||||
indices[0] = 0;
|
||||
indices[1] = 2;
|
||||
indices[2] = 1;
|
||||
indices[3] = 0;
|
||||
indices[4] = 3;
|
||||
indices[5] = 2;
|
||||
Buffer->Vertices.set_used(4);
|
||||
Buffer->Indices.set_used(6);
|
||||
|
||||
vertices[0].TCoords.set(1.0f, 1.0f);
|
||||
vertices[0].Color = colorBottom;
|
||||
Buffer->Indices[0] = 0;
|
||||
Buffer->Indices[1] = 2;
|
||||
Buffer->Indices[2] = 1;
|
||||
Buffer->Indices[3] = 0;
|
||||
Buffer->Indices[4] = 3;
|
||||
Buffer->Indices[5] = 2;
|
||||
|
||||
vertices[1].TCoords.set(1.0f, 0.0f);
|
||||
vertices[1].Color = colorTop;
|
||||
Buffer->Vertices[0].TCoords.set(1.0f, 1.0f);
|
||||
Buffer->Vertices[0].Color = colorBottom;
|
||||
|
||||
vertices[2].TCoords.set(0.0f, 0.0f);
|
||||
vertices[2].Color = colorTop;
|
||||
Buffer->Vertices[1].TCoords.set(1.0f, 0.0f);
|
||||
Buffer->Vertices[1].Color = colorTop;
|
||||
|
||||
vertices[3].TCoords.set(0.0f, 1.0f);
|
||||
vertices[3].Color = colorBottom;
|
||||
Buffer->Vertices[2].TCoords.set(0.0f, 0.0f);
|
||||
Buffer->Vertices[2].Color = colorTop;
|
||||
|
||||
Buffer->Vertices[3].TCoords.set(0.0f, 1.0f);
|
||||
Buffer->Vertices[3].Color = colorBottom;
|
||||
}
|
||||
|
||||
CBillboardSceneNode::~CBillboardSceneNode()
|
||||
{
|
||||
Buffer->drop();
|
||||
}
|
||||
|
||||
//! pre render event
|
||||
void CBillboardSceneNode::OnRegisterSceneNode()
|
||||
|
@ -66,7 +74,25 @@ void CBillboardSceneNode::render()
|
|||
return;
|
||||
|
||||
// make billboard look to camera
|
||||
updateMesh(camera);
|
||||
|
||||
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
|
||||
driver->setMaterial(Buffer->Material);
|
||||
driver->drawMeshBuffer(Buffer);
|
||||
|
||||
if (DebugDataVisible & scene::EDS_BBOX)
|
||||
{
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
video::SMaterial m;
|
||||
m.Lighting = false;
|
||||
driver->setMaterial(m);
|
||||
driver->draw3DBox(BBoxSafe, video::SColor(0,208,195,152));
|
||||
}
|
||||
}
|
||||
|
||||
void CBillboardSceneNode::updateMesh(const irr::scene::ICameraSceneNode* camera)
|
||||
{
|
||||
// billboard looks toward camera
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
|
||||
core::vector3df campos = camera->getAbsolutePosition();
|
||||
|
@ -91,6 +117,8 @@ void CBillboardSceneNode::render()
|
|||
|
||||
view *= -1.0f;
|
||||
|
||||
core::array<video::S3DVertex>& vertices = Buffer->Vertices;
|
||||
|
||||
for (s32 i=0; i<4; ++i)
|
||||
vertices[i].Normal = view;
|
||||
|
||||
|
@ -105,33 +133,23 @@ void CBillboardSceneNode::render()
|
|||
vertices[2].Pos = pos - topHorizontal - vertical;
|
||||
vertices[3].Pos = pos - horizontal + vertical;
|
||||
|
||||
// draw
|
||||
|
||||
if (DebugDataVisible & scene::EDS_BBOX)
|
||||
{
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
video::SMaterial m;
|
||||
m.Lighting = false;
|
||||
driver->setMaterial(m);
|
||||
driver->draw3DBox(BBox, video::SColor(0,208,195,152));
|
||||
}
|
||||
|
||||
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
|
||||
|
||||
driver->setMaterial(Material);
|
||||
|
||||
driver->drawIndexedTriangleList(vertices, 4, indices, 2);
|
||||
Buffer->recalculateBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CBillboardSceneNode::getBoundingBox() const
|
||||
{
|
||||
return BBox;
|
||||
// Really wrong when scaled.
|
||||
return BBoxSafe;
|
||||
}
|
||||
|
||||
const core::aabbox3d<f32>& CBillboardSceneNode::getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) _IRR_OVERRIDE_
|
||||
{
|
||||
updateMesh(camera);
|
||||
return Buffer->BoundingBox;
|
||||
}
|
||||
|
||||
//! sets the size of the billboard
|
||||
void CBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
|
||||
{
|
||||
Size = size;
|
||||
|
@ -144,8 +162,8 @@ void CBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
|
|||
Size.Height = 1.0f;
|
||||
|
||||
const f32 avg = (Size.Width + Size.Height)/6;
|
||||
BBox.MinEdge.set(-avg,-avg,-avg);
|
||||
BBox.MaxEdge.set(avg,avg,avg);
|
||||
BBoxSafe.MinEdge.set(-avg,-avg,-avg);
|
||||
BBoxSafe.MaxEdge.set(avg,avg,avg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -164,14 +182,14 @@ void CBillboardSceneNode::setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWi
|
|||
}
|
||||
|
||||
const f32 avg = (core::max_(Size.Width,TopEdgeWidth) + Size.Height)/6;
|
||||
BBox.MinEdge.set(-avg,-avg,-avg);
|
||||
BBox.MaxEdge.set(avg,avg,avg);
|
||||
BBoxSafe.MinEdge.set(-avg,-avg,-avg);
|
||||
BBoxSafe.MaxEdge.set(avg,avg,avg);
|
||||
}
|
||||
|
||||
|
||||
video::SMaterial& CBillboardSceneNode::getMaterial(u32 i)
|
||||
{
|
||||
return Material;
|
||||
return Buffer->Material;
|
||||
}
|
||||
|
||||
|
||||
|
@ -207,8 +225,8 @@ void CBillboardSceneNode::serializeAttributes(io::IAttributes* out, io::SAttribu
|
|||
out->addFloat("Width", Size.Width);
|
||||
out->addFloat("TopEdgeWidth", TopEdgeWidth);
|
||||
out->addFloat("Height", Size.Height);
|
||||
out->addColor("Shade_Top", vertices[1].Color);
|
||||
out->addColor("Shade_Down", vertices[0].Color);
|
||||
out->addColor("Shade_Top", Buffer->Vertices[1].Color);
|
||||
out->addColor("Shade_Down", Buffer->Vertices[0].Color);
|
||||
}
|
||||
|
||||
|
||||
|
@ -228,10 +246,10 @@ void CBillboardSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttrib
|
|||
}
|
||||
else
|
||||
setSize(Size);
|
||||
vertices[1].Color = in->getAttributeAsColor("Shade_Top");
|
||||
vertices[0].Color = in->getAttributeAsColor("Shade_Down");
|
||||
vertices[2].Color = vertices[1].Color;
|
||||
vertices[3].Color = vertices[0].Color;
|
||||
Buffer->Vertices[1].Color = in->getAttributeAsColor("Shade_Top");
|
||||
Buffer->Vertices[0].Color = in->getAttributeAsColor("Shade_Down");
|
||||
Buffer->Vertices[2].Color = Buffer->Vertices[1].Color;
|
||||
Buffer->Vertices[3].Color = Buffer->Vertices[0].Color;
|
||||
}
|
||||
|
||||
|
||||
|
@ -240,7 +258,7 @@ void CBillboardSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttrib
|
|||
void CBillboardSceneNode::setColor(const video::SColor& overallColor)
|
||||
{
|
||||
for(u32 vertex = 0; vertex < 4; ++vertex)
|
||||
vertices[vertex].Color = overallColor;
|
||||
Buffer->Vertices[vertex].Color = overallColor;
|
||||
}
|
||||
|
||||
|
||||
|
@ -250,10 +268,10 @@ void CBillboardSceneNode::setColor(const video::SColor& overallColor)
|
|||
void CBillboardSceneNode::setColor(const video::SColor& topColor,
|
||||
const video::SColor& bottomColor)
|
||||
{
|
||||
vertices[0].Color = bottomColor;
|
||||
vertices[1].Color = topColor;
|
||||
vertices[2].Color = topColor;
|
||||
vertices[3].Color = bottomColor;
|
||||
Buffer->Vertices[0].Color = bottomColor;
|
||||
Buffer->Vertices[1].Color = topColor;
|
||||
Buffer->Vertices[2].Color = topColor;
|
||||
Buffer->Vertices[3].Color = bottomColor;
|
||||
}
|
||||
|
||||
|
||||
|
@ -263,8 +281,8 @@ void CBillboardSceneNode::setColor(const video::SColor& topColor,
|
|||
void CBillboardSceneNode::getColor(video::SColor& topColor,
|
||||
video::SColor& bottomColor) const
|
||||
{
|
||||
bottomColor = vertices[0].Color;
|
||||
topColor = vertices[1].Color;
|
||||
bottomColor = Buffer->Vertices[0].Color;
|
||||
topColor = Buffer->Vertices[1].Color;
|
||||
}
|
||||
|
||||
|
||||
|
@ -280,7 +298,7 @@ ISceneNode* CBillboardSceneNode::clone(ISceneNode* newParent, ISceneManager* new
|
|||
newManager, ID, RelativeTranslation, Size);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->Material = Material;
|
||||
nb->Buffer->Material = Buffer->Material;
|
||||
nb->Size = Size;
|
||||
nb->TopEdgeWidth = this->TopEdgeWidth;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#define __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IBillboardSceneNode.h"
|
||||
#include "S3DVertex.h"
|
||||
#include "SMeshBuffer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
@ -25,6 +25,8 @@ public:
|
|||
video::SColor colorTop=video::SColor(0xFFFFFFFF),
|
||||
video::SColor colorBottom=video::SColor(0xFFFFFFFF));
|
||||
|
||||
virtual ~CBillboardSceneNode();
|
||||
|
||||
//! pre render event
|
||||
virtual void OnRegisterSceneNode() _IRR_OVERRIDE_;
|
||||
|
||||
|
@ -67,6 +69,9 @@ public:
|
|||
virtual void getColor(video::SColor& topColor,
|
||||
video::SColor& bottomColor) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Get the real boundingbox used by the billboard (which depends on the active camera)
|
||||
virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) _IRR_OVERRIDE_;
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const _IRR_OVERRIDE_;
|
||||
|
||||
|
@ -79,16 +84,24 @@ public:
|
|||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) _IRR_OVERRIDE_;
|
||||
|
||||
protected:
|
||||
void updateMesh(const irr::scene::ICameraSceneNode* camera);
|
||||
|
||||
private:
|
||||
|
||||
//! Size.Width is the bottom edge width
|
||||
core::dimension2d<f32> Size;
|
||||
f32 TopEdgeWidth;
|
||||
core::aabbox3d<f32> BBox;
|
||||
video::SMaterial Material;
|
||||
|
||||
video::S3DVertex vertices[4];
|
||||
u16 indices[6];
|
||||
//! BoundingBox which is large enough to contain the billboard independent of the camera
|
||||
// TODO: BUG - still can be wrong with scaling < 1. Billboards should calculate relative coordinates for their mesh
|
||||
// and then use the node-scaling. But needs some work...
|
||||
/** Note that we can't use the real boundingbox for culling because at that point
|
||||
the camera which is used to calculate the billboard is not yet updated. So we only
|
||||
know the real boundingbox after rendering - which is too late for culling. */
|
||||
core::aabbox3d<f32> BBoxSafe;
|
||||
|
||||
scene::SMeshBuffer* Buffer;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -281,6 +281,25 @@ void CBillboardTextSceneNode::OnAnimate(u32 timeMs)
|
|||
if (!camera)
|
||||
return;
|
||||
|
||||
// TODO: Risky - if camera is later in the scene-graph then it's not yet updated here
|
||||
// CBillBoardSceneNode does it different, but maybe real solution would be to enforce cameras to update earlier?
|
||||
// Maybe we can also unify the code by using a common base-class or having updateMesh functionality in an animator instead.
|
||||
updateMesh(camera);
|
||||
|
||||
// mesh uses vertices with absolute coordinates so to get a bbox for culling we have to get back to local ones.
|
||||
BBox = Mesh->getBoundingBox();
|
||||
core::matrix4 mat( getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE );
|
||||
mat.transformBoxEx(BBox);
|
||||
}
|
||||
|
||||
const core::aabbox3d<f32>& CBillboardTextSceneNode::getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera)
|
||||
{
|
||||
updateMesh(camera);
|
||||
return Mesh->getBoundingBox();
|
||||
}
|
||||
|
||||
void CBillboardTextSceneNode::updateMesh(const irr::scene::ICameraSceneNode* camera)
|
||||
{
|
||||
// get text width
|
||||
f32 textLength = 0.f;
|
||||
u32 i;
|
||||
|
@ -347,14 +366,9 @@ void CBillboardTextSceneNode::OnAnimate(u32 timeMs)
|
|||
}
|
||||
|
||||
// make bounding box
|
||||
|
||||
for (i=0; i< Mesh->getMeshBufferCount() ; ++i)
|
||||
Mesh->getMeshBuffer(i)->recalculateBoundingBox();
|
||||
Mesh->recalculateBoundingBox();
|
||||
|
||||
BBox = Mesh->getBoundingBox();
|
||||
core::matrix4 mat( getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE );
|
||||
mat.transformBoxEx(BBox);
|
||||
}
|
||||
|
||||
void CBillboardTextSceneNode::OnRegisterSceneNode()
|
||||
|
|
|
@ -17,6 +17,8 @@ namespace irr
|
|||
namespace scene
|
||||
{
|
||||
|
||||
class ICameraSceneNode;
|
||||
|
||||
class CTextSceneNode : public ITextSceneNode
|
||||
{
|
||||
public:
|
||||
|
@ -141,6 +143,11 @@ namespace scene
|
|||
topEdgeWidth = Size.Width;
|
||||
}
|
||||
|
||||
virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) _IRR_OVERRIDE_;
|
||||
|
||||
protected:
|
||||
void updateMesh(const irr::scene::ICameraSceneNode* camera);
|
||||
|
||||
private:
|
||||
|
||||
core::stringw Text;
|
||||
|
|
Loading…
Reference in New Issue