Use a temp variable when calculating a merged world bounding box, as OnWorldBoundingBoxUpdate() may be called re-entrantly from multiple worker threads.

This commit is contained in:
Lasse Öörni 2013-09-19 08:53:58 +00:00
parent 41f627b230
commit 9443cce235
3 changed files with 16 additions and 10 deletions

View File

@ -310,13 +310,12 @@ const PODVector<unsigned char>& BillboardSet::GetNetBillboardsAttr() const
void BillboardSet::OnWorldBoundingBoxUpdate()
{
worldBoundingBox_.defined_ = false;
unsigned enabledBillboards = 0;
const Matrix3x4& worldTransform = node_->GetWorldTransform();
Matrix3x4 billboardTransform = relative_ ? worldTransform : Matrix3x4::IDENTITY;
Vector3 billboardScale = scaled_ ? worldTransform.Scale() : Vector3::ONE;
BoundingBox worldBox;
for (unsigned i = 0; i < billboards_.Size(); ++i)
{
if (!billboards_[i].enabled_)
@ -325,14 +324,16 @@ void BillboardSet::OnWorldBoundingBoxUpdate()
float size = INV_SQRT_TWO * (billboards_[i].size_.x_ * billboardScale.x_ + billboards_[i].size_.y_ * billboardScale.y_);
Vector3 center = billboardTransform * billboards_[i].position_;
Vector3 edge = Vector3::ONE * size;
worldBoundingBox_.Merge(BoundingBox(center - edge, center + edge));
worldBox.Merge(BoundingBox(center - edge, center + edge));
++enabledBillboards;
}
// If no billboards enabled, the bounding box is just the node's world position
if (!enabledBillboards)
worldBoundingBox_.Merge(node_->GetWorldPosition());
worldBox.Merge(node_->GetWorldPosition());
worldBoundingBox_ = worldBox;
}
void BillboardSet::UpdateBufferSize()

View File

@ -661,7 +661,7 @@ void DecalSet::OnWorldBoundingBoxUpdate()
else
{
// When using skinning, update world bounding box based on the bones
worldBoundingBox_.defined_ = false;
BoundingBox worldBox;
for (Vector<Bone>::ConstIterator i = bones_.Begin(); i != bones_.End(); ++i)
{
@ -672,10 +672,12 @@ void DecalSet::OnWorldBoundingBoxUpdate()
// Use hitbox if available. If not, use only half of the sphere radius
/// \todo The sphere radius should be multiplied with bone scale
if (i->collisionMask_ & BONECOLLISION_BOX)
worldBoundingBox_.Merge(i->boundingBox_.Transformed(boneNode->GetWorldTransform()));
worldBox.Merge(i->boundingBox_.Transformed(boneNode->GetWorldTransform()));
else if (i->collisionMask_ & BONECOLLISION_SPHERE)
worldBoundingBox_.Merge(Sphere(boneNode->GetWorldPosition(), i->radius_ * 0.5f));
worldBox.Merge(Sphere(boneNode->GetWorldPosition(), i->radius_ * 0.5f));
}
worldBoundingBox_ = worldBox;
}
}

View File

@ -351,9 +351,10 @@ void StaticModelGroup::OnNodeSetEnabled(Node* node)
void StaticModelGroup::OnWorldBoundingBoxUpdate()
{
// Update transforms and bounding box at the same time to have to go through the objects only once
worldBoundingBox_.defined_ = false;
unsigned index = 0;
BoundingBox worldBox;
for (unsigned i = 0; i < instanceNodes_.Size(); ++i)
{
Node* node = instanceNodes_[i];
@ -362,9 +363,11 @@ void StaticModelGroup::OnWorldBoundingBoxUpdate()
const Matrix3x4& worldTransform = node->GetWorldTransform();
worldTransforms_[index++] = worldTransform;
worldBoundingBox_.Merge(boundingBox_.Transformed(worldTransform));
worldBox.Merge(boundingBox_.Transformed(worldTransform));
}
worldBoundingBox_ = worldBox;
// Store the amount of valid instances we found instead of resizing worldTransforms_. This is because this function may be
// called from multiple worker threads simultaneously
numWorldTransforms_ = index;