OBB calculating extents

Started by
3 comments, last by Juliean 10 years, 10 months ago

Hello,

I've just implemented basic OBB vs OBB collision detectedion. My OBB is represented by a center, 3 perpenticular normals defining the orientation axis, and the maximal extents on each of its own axis. I'm wonding now, how would I correctly calculate these extents? As long as the OBB is in fact axis aligned, I was able to just max() the absolute values of each axis, but since I'm using the OBB to have oriented boxes (duh) the extent calculation fails. Obviously, the extents must be in the

This is the constructor of my OBB:


        OBB::OBB(const Vector3& vCenter, const Vector3& vNrm1, const Vector3& vNrm2, const Vector3& vNrm3): BaseVolume(vCenter)
        {
            m_vNrm[0] = vNrm1.normal();
            m_vNrm[1] = vNrm2.normal();
            m_vNrm[2] = vNrm3.normal();

            m_vExtent = vNrm1.abs().max(vNrm2.abs()).max(vNrm3.abs()); // this does only work for axis aligned OBBs
        }

Any ideas on how to calculate that extent corretly?

EDIT: Damn, I found the solution just seconds after posting this.


m_vExtent.x = m_vNrm1.length();
m_vExtent.y = m_vNrm2.length();
m_vExtents.z = m_vNrm3.length();


So easy -.- My thinking must be restrained by the ongoing work. Oh well, in case someone comes across a similar problem and is as confused as I am, here is the solution...

Advertisement

There are some things about your presentation that are worrisome to me, in terms of language use, variable names, and coding style. I offer some suggestions, which you can use if you find them useful.

First, you say that your OBB's having "3 perpendicular normals," but I wonder why you call them normals. Is it because the faces of the OBB are perpendicular to these vectors that you called them "normals?" Why not call them just local coordinate frame axes, or basis vectors, or basis directions, all of which are more general and more appropriate for vectors that define the rotation of a generalized shape? I would also suggest that you completely separate the dimensions of the OBB from the basis vectors in the constructor, for clarity. Embedding the size of the OBB inside the incoming basis vectors...is confusing. There is nothing in the variable names of the OBB constructor parameters that indicates the length of the edges is equal to the length of those vectors.

If I were to write a simple OBB class, it'd look something like this. This is just quickly written code, incomplete, not really designed, not tested, and not exactly what I'd use for a project. This code illustrates an idea. The idea is to suggest building your transformation (location and orientation) as a separate object and just include it in the OBB class. By building the transformation separately, you can re-use it to represent other things in the scene, too. Not just OBB's.


/// simple 3x3 matrix class, to be used to store orientation as a 3x3
/// rotation matrix
class RotationMatrix3x3
{
public:
    RotationMatrix3x3(const vec3 &xDir, const vec3 &yDir, const vec3 &zDir)
    {
        m_basisVectors[0] = xDir;
        m_basisVectors[1] = yDir;
        m_basisVectors[2] = zDir;
    }

protected:
   vec3 m_basisVectors[3]; ///< x, y, and z direction basis vectors
};

/// transformation class to be used to store translation and rotation
/// relative to a parent or world Cartesian coordinate frame
class Transform
{
public:
    Transform(const vec3 &translation, const vec3 &xDir, const vec3 &yDir,
              const vec3 &zDir):
              m_translation(translation), m_orientation(xDir, yDir, zDir)
    {
    }

protected:
    /// translation vector, represented in a parent or world coordinate frame
    vec3 m_translation;

    /// orientation as a 3x3 rotation matrix, represented in a parent or world
    /// coordinate frame
    RotationMatrix3x3 m_orientation;
};

/// Oriented Bounding Box class, which inherits its location and orientation
/// relative to a parent or world coordinate frame via the Transform class
class OBB : public Transform
{
    OBB(const vec3 &translation, const vec3 &xDir, const vec3 &yDir,
        const vec3 &zDir, const vec3 &extent) :
        Transform(translation, xDir, yDir, zDir), m_extent(extent)
    {
    }

protected:
    /// extent along local object basis directions
    vec3 m_extent;
};

I hope this is somehow useful.

grhodes_at_work

Graham Rhodes Moderator, Math & Physics forum @ gamedev.net

There are some things about your presentation that are worrisome to me, in terms of language use, variable names, and coding style. I offer some suggestions, which you can use if you find them useful.

Thanks you, I really appreciate any feedback one gives me!

First, you say that your OBB's having "3 perpendicular normals," but I wonder why you call them normals. Is it because the faces of the OBB are perpendicular to these vectors that you called them "normals?" Why not call them just local coordinate frame axes, or basis vectors, or basis directions, all of which are more general and more appropriate for vectors that define the rotation of a generalized shape?

As for "why", I've been following this german article, which was the only one I could find that offered a reasonable algorythm for OBBvsOBB-collision detection, so I sorta adapted its terminology. I'll clean that up following your suggestions.

I would also suggest that you completely separate the dimensions of the OBB from the basis vectors in the constructor, for clarity. Embedding the size of the OBB inside the incoming basis vectors...is confusing.

I totally agree, I was too much under pressure to think about such small things at the momement, but I also think it makes sense to seperate the extents from the normal vectors.

The idea is to suggest building your transformation (location and orientation) as a separate object and just include it in the OBB class. By building the transformation separately, you can re-use it to represent other things in the scene, too. Not just OBB's.

While the idea definately sounds nice, its not really practially for two reasons. First of all, my engine is mainly based around components, and so there already is a "transform" component, which is being used for the scene graph etc... inheriting the OBB from this component is out of the question, and also adding a "transform" class on top as an additional level of abstraction, I don't really think its partical for me. Second point, I'm actually building a collision libary similar to Box2D or others, so it wouldn't make to much sense to couple the OBB to a class the might also be used in the scene graph etc..., would it?

Thanks anyway for all your suggestions, I sure took something useful from it.

Thank you for the additional background information. I now understand better what you are doing, and what your references are.

I hope I'm not overstepping your bounds to make additional suggestions and send additional references.

With respect to the separate transform object, I agree that you wouldn't want to create a new transform class. And, certainly, it does not necessarily make sense for OBB to inherit from transform. The OBB could have a property that is a transform object, and I wonder if it might still make sense to take advantage of the existing scene graph transform class. If you do something like this in your collision detection engine, then it might make it easier to sync your collision detection with the scene graph to be rendered. Or, the OBB shape could be a child of a transform object...making it easier to support compound shapes or different types of collision shapes. Many physics engines are set up sort of like this. I realize that rendering engines and collision detection/physics engines often have separate representations of the scene, but the collision/physics engines usually provide helpful built-in mechanisms to point back to a rendered scene graph.

I can think of another OBB reference, which might be useful if you can find a copy online. It is the OBBTree paper written by researchers at UNC Chapel Hill many years ago. Yes, its really old now, but is one of the early presentations of OBB for collision detection, and still useful. Here is a link to the paper. (I admit that I haven't ready it in a long, long time.)

http://www.cs.unc.edu/~walk/papers/gottscha/sig96.pdf

Pierre Terdiman also has done some work that you might find useful:

http://www.codercorner.com/Coder.htm - see OPCODE for example

http://www.codercorner.com/RAPID_Hack.htm

Graham

Graham Rhodes Moderator, Math & Physics forum @ gamedev.net

Thanks again for your helpfull comment,

no way you've been overstepping any bounds, I'm totally glad for any positive suggestion one can make. Just wanted to say that, under this aspect, I see how such a transform class would be a helpful addition to my phyiscs libary. Once I actually start working on those (for the current game project I'm just using plain "Does X collide with Y"? checks whenever needed) I'll implement it and backtrack to the OBB - should be an easy task since I've seperated the collision objects interface enough from the implementation.

Also, thanks for the links, I'll have a close look at them, I'm pretty sure the OBB-collision implementation is really slow, at least its a bit messy and seems to do an aweful lot of work.

This topic is closed to new replies.

Advertisement