1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
// Geometric Tools, LLC
// Copyright (c) 1998-2014
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
//
// File Version: 5.0.0 (2010/01/01)
#include "Wm5GraphicsPCH.h"
#include "Wm5BillboardNode.h"
using namespace Wm5;
WM5_IMPLEMENT_RTTI(Wm5, Node, BillboardNode);
WM5_IMPLEMENT_STREAM(BillboardNode);
WM5_IMPLEMENT_FACTORY(BillboardNode);
//----------------------------------------------------------------------------
BillboardNode::BillboardNode (Camera* camera)
:
mCamera(camera)
{
}
//----------------------------------------------------------------------------
BillboardNode::~BillboardNode ()
{
}
//----------------------------------------------------------------------------
void BillboardNode::UpdateWorldData (double applicationTime)
{
// Compute the billboard's world transforms based on its parent's world
// transform and its local transforms. Notice that you should not call
// Node::UpdateWorldData since that function updates its children. The
// children of a BillboardNode cannot be updated until the billboard is
// aligned with the camera.
Spatial::UpdateWorldData(applicationTime);
if (mCamera)
{
// Inverse-transform the camera to the model space of the billboard.
APoint modelPos = WorldTransform.Inverse()*mCamera->GetPosition();
// To align the billboard, the projection of the camera to the
// xz-plane of the billboard's model space determines the angle of
// rotation about the billboard's model y-axis. If the projected
// camera is on the model axis (x = 0 and z = 0), ATan2 returns zero
// (rather than NaN), so there is no need to trap this degenerate
// case and handle it separately.
float angle = Mathf::ATan2(modelPos[0], modelPos[2]);
HMatrix orient(AVector::UNIT_Y, angle);
WorldTransform.SetRotate(WorldTransform.GetRotate()*orient);
}
// Update the children now that the billboard orientation is known.
std::vector<SpatialPtr>::iterator iter = mChild.begin();
std::vector<SpatialPtr>::iterator end = mChild.end();
for (/**/; iter != end; ++iter)
{
Spatial* child = *iter;
if (child)
{
child->Update(applicationTime, false);
}
}
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Name support.
//----------------------------------------------------------------------------
Object* BillboardNode::GetObjectByName (const std::string& name)
{
Object* found = Object::GetObjectByName(name);
if (found)
{
return found;
}
WM5_GET_OBJECT_BY_NAME(mCamera, name, found);
return 0;
}
//----------------------------------------------------------------------------
void BillboardNode::GetAllObjectsByName (const std::string& name,
std::vector<Object*>& objects)
{
Node::GetAllObjectsByName(name, objects);
WM5_GET_ALL_OBJECTS_BY_NAME(mCamera, name, objects);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Streaming support.
//----------------------------------------------------------------------------
BillboardNode::BillboardNode (LoadConstructor value)
:
Node(value),
mCamera(0)
{
}
//----------------------------------------------------------------------------
void BillboardNode::Load (InStream& source)
{
WM5_BEGIN_DEBUG_STREAM_LOAD(source);
Node::Load(source);
source.ReadPointer(mCamera);
WM5_END_DEBUG_STREAM_LOAD(BillboardNode, source);
}
//----------------------------------------------------------------------------
void BillboardNode::Link (InStream& source)
{
Node::Link(source);
source.ResolveLink(mCamera);
}
//----------------------------------------------------------------------------
void BillboardNode::PostLink ()
{
Node::PostLink();
}
//----------------------------------------------------------------------------
bool BillboardNode::Register (OutStream& target) const
{
if (Node::Register(target))
{
target.Register(mCamera);
return true;
}
return false;
}
//----------------------------------------------------------------------------
void BillboardNode::Save (OutStream& target) const
{
WM5_BEGIN_DEBUG_STREAM_SAVE(target);
Node::Save(target);
target.WritePointer(mCamera);
WM5_END_DEBUG_STREAM_SAVE(BillboardNode, target);
}
//----------------------------------------------------------------------------
int BillboardNode::GetStreamingSize () const
{
int size = Node::GetStreamingSize();
size += WM5_POINTERSIZE(mCamera);
return size;
}
//----------------------------------------------------------------------------
|