GRIM: Fix bounding box calculation. Fix #391

This commit is contained in:
Giulio Camuffo 2011-10-18 17:42:12 +02:00
parent 611a4ff086
commit 46a8d461e0
7 changed files with 79 additions and 48 deletions

View file

@ -1445,6 +1445,7 @@ bool Actor::collidesWith(Actor *actor, Math::Vector3d *vec) const {
Math::Vector3d bboxPos;
Math::Vector3d size;
float scale;
Math::Vector3d pos;
Math::Vector3d circlePos;
Math::Angle yaw;
@ -1455,7 +1456,8 @@ bool Actor::collidesWith(Actor *actor, Math::Vector3d *vec) const {
if (mode1 == CollisionBox) {
pos = p1 + *vec;
bboxPos = pos + model1->_bboxPos;
size = model1->_bboxSize * _collisionScale;
size = model1->_bboxSize;
scale = _collisionScale;
yaw = _yaw;
circle.setX(p2.x());
@ -1465,7 +1467,8 @@ bool Actor::collidesWith(Actor *actor, Math::Vector3d *vec) const {
} else {
pos = p2;
bboxPos = p2 + model2->_bboxPos;
size = model2->_bboxSize * actor->_collisionScale;
size = model2->_bboxSize;
scale = actor->_collisionScale;
yaw = actor->_yaw;
circle.setX(p1.x() + vec->x());
@ -1478,6 +1481,8 @@ bool Actor::collidesWith(Actor *actor, Math::Vector3d *vec) const {
rect._topRight = Math::Vector2d(bboxPos.x() + size.x(), bboxPos.y() + size.y());
rect._bottomLeft = Math::Vector2d(bboxPos.x(), bboxPos.y());
rect._bottomRight = Math::Vector2d(bboxPos.x() + size.x(), bboxPos.y());
rect.scale(scale);
rect.rotateAround(Math::Vector2d(pos.x(), pos.y()), yaw);
if (rect.intersectsCircle(circle, radius)) {

View file

@ -65,28 +65,23 @@ Model::Model(const Common::String &filename, const char *data, int len, CMap *cm
ModelNode &node = _rootHierNode[i];
if (node._mesh) {
Mesh &mesh = *node._mesh;
//NOTE: Setting p to mesh._matrix._pos seems more similar to original
// but, as in original, it also stops manny quite far away from the
// bone wagon when approaching it from behind in set sg.
// Using the node position looks instead more realistic, but, on the
// other hand, it may not work right in all cases.
Math::Vector3d p = node._matrix.getPosition();
Math::Vector3d p = mesh._matrix.getPosition();
float x = p.x();
float y = p.y();
float z = p.z();
for (int k = 0; k < mesh._numVertices * 3; k += 3) {
if (first || mesh._vertices[k] + x < _bboxPos.x())
_bboxPos.x() = mesh._vertices[k] + x;
if (mesh._vertices[k + 1] + y < _bboxPos.y())
if (first || mesh._vertices[k + 1] + y < _bboxPos.y())
_bboxPos.y() = mesh._vertices[k + 1] + y;
if (mesh._vertices[k + 2] + z < _bboxPos.z())
if (first || mesh._vertices[k + 2] + z < _bboxPos.z())
_bboxPos.z() = mesh._vertices[k + 2] + z;
if (first || mesh._vertices[k] + x > max.x())
max.x() = mesh._vertices[k] + x;
if (mesh._vertices[k + 1] + y > max.y())
if (first || mesh._vertices[k + 1] + y > max.y())
max.y() = mesh._vertices[k + 1] + y;
if (mesh._vertices[k + 2] + z > max.z())
if (first || mesh._vertices[k + 2] + z > max.z())
max.z() = mesh._vertices[k + 2] + z;
first = false;
@ -653,36 +648,40 @@ void ModelNode::removeChild(ModelNode *child) {
void ModelNode::setMatrix(Math::Matrix4 matrix) {
_matrix = matrix;
if (_sibling)
_sibling->setMatrix(matrix);
}
void ModelNode::update() {
if (!_initialized)
return;
Math::Vector3d animPos = _pos + _animPos;
Math::Angle animPitch = _pitch + _animPitch;
Math::Angle animYaw = _yaw + _animYaw;
Math::Angle animRoll = _roll + _animRoll;
if (_hierVisible) {
Math::Vector3d animPos = _pos + _animPos;
Math::Angle animPitch = _pitch + _animPitch;
Math::Angle animYaw = _yaw + _animYaw;
Math::Angle animRoll = _roll + _animRoll;
_localMatrix.setPosition(animPos);
_localMatrix.buildFromPitchYawRoll(animPitch, animYaw, animRoll);
_localMatrix.setPosition(animPos);
_localMatrix.buildFromPitchYawRoll(animPitch, animYaw, animRoll);
_matrix = _localMatrix * _matrix;
_matrix = _matrix * _localMatrix;
_pivotMatrix = _matrix;
_pivotMatrix = _matrix;
_pivotMatrix.translate(_pivot);
_pivotMatrix.translate(_pivot);
if (_mesh) {
_mesh->_matrix = _pivotMatrix;
}
if (_mesh) {
_mesh->_matrix = _pivotMatrix;
if (_child) {
_child->setMatrix(_matrix);
_child->update();
}
}
ModelNode *child = _child;
while (child) {
child->setMatrix(_matrix);
child->update();
child = child->_sibling;
if (_sibling) {
_sibling->update();
}
}

View file

@ -49,22 +49,22 @@ void Matrix<4, 4>::transform(Vector3d *v, bool trans) const {
}
Vector3d Matrix<4, 4>::getPosition() const {
return Vector3d(getValue(3, 0), getValue(3, 1), getValue(3, 2));
return Vector3d(getValue(0, 3), getValue(1, 3), getValue(2, 3));
}
void Matrix<4, 4>::setPosition(const Vector3d &v) {
setValue(3, 0, v.x());
setValue(3, 1, v.y());
setValue(3, 2, v.z());
setValue(0, 3, v.x());
setValue(1, 3, v.y());
setValue(2, 3, v.z());
}
void Matrix<4, 4>::translate(const Vector3d &vec) {
Vector3d v(vec);
transform(&v, false);
operator()(3, 0) += v.x();
operator()(3, 1) += v.y();
operator()(3, 2) += v.z();
operator()(0, 3) += v.x();
operator()(1, 3) += v.y();
operator()(2, 3) += v.z();
}
} // end of namespace Math

View file

@ -64,6 +64,30 @@ void Rect2d::rotateAroundCenter(const Angle &angle) {
rotateAround(center, angle);
}
void Rect2d::moveCenterTo(const Vector2d &pos) {
Vector2d vec(pos - getCenter());
translate(vec);
}
void Rect2d::scale(float amount) {
Vector2d c = getCenter();
moveCenterTo(Vector2d(0, 0));
_topLeft *= amount;
_topRight *= amount;
_bottomLeft *= amount;
_bottomRight *= amount;
moveCenterTo(c);
}
void Rect2d::translate(const Vector2d &vec) {
_topLeft += vec;
_topRight += vec;
_bottomLeft += vec;
_bottomRight += vec;
}
bool Rect2d::intersectsRect(const Rect2d &rect) const {
// TODO: implement this;
error("Rect2d::intersectsRect not implemented");

View file

@ -41,6 +41,9 @@ public:
void rotateAround(const Vector2d &point, const Angle &angle);
void rotateAroundCenter(const Angle &angle);
void moveCenterTo(const Vector2d &pos);
void scale(float amount);
void translate(const Vector2d &vec);
bool intersectsRect(const Rect2d &rect) const;
bool intersectsCircle(const Vector2d &center, float radius) const;
bool containsPoint(const Vector2d &point) const;

View file

@ -72,9 +72,9 @@ void Rotation3D<T>::buildFromPitchYawRoll(const Angle &pitch, const Angle &yaw,
// at, around x-axis
template<class T>
void Rotation3D<T>::buildAroundRoll(const Angle &roll) {
float cosa = roll.getCosine();
float sina = roll.getSine();
void Rotation3D<T>::buildAroundPitch(const Angle &pitch) {
float cosa = pitch.getCosine();
float sina = pitch.getSine();
this->getMatrix().getRow(0) << 1.f << 0.f << 0.f;
this->getMatrix().getRow(1) << 0.f << cosa << -sina;
@ -83,9 +83,9 @@ void Rotation3D<T>::buildAroundRoll(const Angle &roll) {
// right
template<class T>
void Rotation3D<T>::buildAroundPitch(const Angle &pitch) {
float cosa = pitch.getCosine();
float sina = pitch.getSine();
void Rotation3D<T>::buildAroundRoll(const Angle &roll) {
float cosa = roll.getCosine();
float sina = roll.getSine();
this->getMatrix().getRow(0) << cosa << 0.f << sina;
this->getMatrix().getRow(1) << 0.f << 1.f << 0.f;
@ -111,15 +111,15 @@ void Rotation3D<T>::getPitchYawRoll(Angle *pPitch, Angle *pYaw, Angle *pRoll) co
this->getMatrix().getValue(0, 0));
}
if (pPitch) {
if (pRoll) {
float a = this->getMatrix().getValue(2, 1);
float b = this->getMatrix().getValue(2, 2);
float mag = sqrt(a * a + b * b);
*pPitch = Angle::arcTangent2(-this->getMatrix().getValue(2, 0), mag);
*pRoll = Angle::arcTangent2(-this->getMatrix().getValue(2, 0), mag);
}
if (pRoll) {
*pRoll = Angle::arcTangent2(this->getMatrix().getValue(2, 1),
if (pPitch) {
*pPitch = Angle::arcTangent2(this->getMatrix().getValue(2, 1),
this->getMatrix().getValue(2, 2));
}
}

View file

@ -43,7 +43,7 @@ public:
*vec = this->getThis() * *vec;
}
Matrix<dim, dim> operator=(float i);
Matrix<dim, dim> &operator=(float i);
protected:
MatrixType() : MatrixBase<dim, dim>() { setToIdentity(); }
@ -52,7 +52,7 @@ protected:
};
template<int dim>
Matrix<dim, dim> MatrixType<dim, dim>::operator=(float i) {
Matrix<dim, dim> &MatrixType<dim, dim>::operator=(float i) {
for (int row = 0; row < dim; ++row) {
for (int col = 0; col < dim; ++col) {
this->setValue(row, col, (row == col ? i : 0.f));