Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8829407
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 14, 20262026-06-14T07:49:43+00:00 2026-06-14T07:49:43+00:00

I’m working on the physics for my GTA2-like game so I can learn more

  • 0

I’m working on the physics for my GTA2-like game so I can learn more about game physics.

The collision detection and resolution are working great.

I’m now just unsure how to compute the point of contact when I hit a wall.

Here is my OBB class:

public class OBB2D
{
   private Vector2D projVec = new Vector2D();
   private static Vector2D projAVec = new Vector2D();
   private static Vector2D projBVec = new Vector2D();
   private static Vector2D tempNormal = new Vector2D();
   private Vector2D deltaVec = new Vector2D();


// Corners of the box, where 0 is the lower left.
   private  Vector2D corner[] = new Vector2D[4];

   private Vector2D center = new Vector2D();
   private Vector2D extents = new Vector2D();

   private RectF boundingRect = new RectF();
   private float angle;

    //Two edges of the box extended away from corner[0]. 
   private  Vector2D axis[] = new Vector2D[2];

   private double origin[] = new double[2];

   public OBB2D(float centerx, float centery, float w, float h, float angle)
    {
       for(int i = 0; i < corner.length; ++i)
       {
           corner[i] = new Vector2D();
       }
       for(int i = 0; i < axis.length; ++i)
       {
           axis[i] = new Vector2D();
       }
       set(centerx,centery,w,h,angle);
    }

   public OBB2D(float left, float top, float width, float height)
  {
       for(int i = 0; i < corner.length; ++i)
       {
           corner[i] = new Vector2D();
       }
       for(int i = 0; i < axis.length; ++i)
       {
           axis[i] = new Vector2D();
       }
       set(left + (width / 2), top + (height / 2),width,height,0.0f);
   }

   public void set(float centerx,float centery,float w, float h,float angle)
   {
       float vxx = (float)Math.cos(angle);
       float vxy = (float)Math.sin(angle);
       float vyx = (float)-Math.sin(angle);
       float vyy = (float)Math.cos(angle);

           vxx *= w / 2;
           vxy *= (w / 2);
           vyx *= (h / 2);
           vyy *= (h / 2);

           corner[0].x = centerx - vxx - vyx;
           corner[0].y = centery - vxy - vyy;
           corner[1].x = centerx + vxx - vyx;
           corner[1].y = centery + vxy - vyy;
           corner[2].x = centerx + vxx + vyx;
           corner[2].y = centery + vxy + vyy;
           corner[3].x = centerx - vxx + vyx;
           corner[3].y = centery - vxy + vyy;

           this.center.x = centerx;
           this.center.y = centery;
           this.angle = angle;
           computeAxes();
           extents.x = w / 2;
           extents.y = h / 2;

           computeBoundingRect();
   }


   //Updates the axes after the corners move.  Assumes the
   //corners actually form a rectangle.
   private void computeAxes()
   {
       axis[0].x = corner[1].x - corner[0].x;
       axis[0].y = corner[1].y - corner[0].y;
       axis[1].x = corner[3].x - corner[0].x;
       axis[1].y = corner[3].y - corner[0].y;


       // Make the length of each axis 1/edge length so we know any
       // dot product must be less than 1 to fall within the edge.

       for (int a = 0; a < axis.length; ++a) 
       {
        float l = axis[a].length();
        float ll = l * l;
        axis[a].x = axis[a].x / ll;
        axis[a].y = axis[a].y / ll;
           origin[a] = corner[0].dot(axis[a]);
       }
   }



   public void computeBoundingRect()
   {
       boundingRect.left = JMath.min(JMath.min(corner[0].x, corner[3].x), JMath.min(corner[1].x, corner[2].x));
       boundingRect.top = JMath.min(JMath.min(corner[0].y, corner[1].y),JMath.min(corner[2].y, corner[3].y));
       boundingRect.right = JMath.max(JMath.max(corner[1].x, corner[2].x), JMath.max(corner[0].x, corner[3].x));
       boundingRect.bottom = JMath.max(JMath.max(corner[2].y, corner[3].y),JMath.max(corner[0].y, corner[1].y)); 
   }

   public void set(RectF rect)
   {
       set(rect.centerX(),rect.centerY(),rect.width(),rect.height(),0.0f);
   }

    // Returns true if other overlaps one dimension of this.
    private boolean overlaps1Way(OBB2D other)
    {
        for (int a = 0; a < axis.length; ++a) {

            double t = other.corner[0].dot(axis[a]);

            // Find the extent of box 2 on axis a
            double tMin = t;
            double tMax = t;

            for (int c = 1; c < corner.length; ++c) {
                t = other.corner[c].dot(axis[a]);

                if (t < tMin) {
                    tMin = t;
                } else if (t > tMax) {
                    tMax = t;
                }
            }

            // We have to subtract off the origin

            // See if [tMin, tMax] intersects [0, 1]
            if ((tMin > 1 + origin[a]) || (tMax < origin[a])) {
                // There was no intersection along this dimension;
                // the boxes cannot possibly overlap.
                return false;
            }
        }

        // There was no dimension along which there is no intersection.
        // Therefore the boxes overlap.
        return true;
    }



    public void moveTo(float centerx, float centery) 
    {
        float cx,cy;

        cx = center.x;
        cy = center.y;

        deltaVec.x = centerx - cx;
        deltaVec.y  = centery - cy;


        for (int c = 0; c < 4; ++c)
        {
            corner[c].x += deltaVec.x;
            corner[c].y += deltaVec.y;
        }

        boundingRect.left += deltaVec.x;
        boundingRect.top += deltaVec.y;
        boundingRect.right += deltaVec.x;
        boundingRect.bottom += deltaVec.y;


        this.center.x = centerx;
        this.center.y = centery;
        computeAxes();
    }

    // Returns true if the intersection of the boxes is non-empty.
    public boolean overlaps(OBB2D other)
    {
        if(right() < other.left())
        {
            return false;
        }

        if(bottom() < other.top())
        {
            return false;
        }

        if(left() > other.right())
        {
            return false;
        }

        if(top() > other.bottom())
        {
            return false;
        }


        if(other.getAngle() == 0.0f && getAngle() == 0.0f)
        {
            return true;
        }

        return overlaps1Way(other) && other.overlaps1Way(this);
    }

    public Vector2D getCenter()
    {
        return center;
    }

    public float getWidth()
    {
        return extents.x * 2;
    }

    public float getHeight() 
    {
        return extents.y * 2;
    }

    public void setAngle(float angle)
    {
        set(center.x,center.y,getWidth(),getHeight(),angle);
    }

    public float getAngle()
    {
        return angle;
    }

    public void setSize(float w,float h)
    {
        set(center.x,center.y,w,h,angle);
    }

    public float left()
    {
        return boundingRect.left;
    }

    public float right()
    {
        return boundingRect.right;
    }

    public float bottom()
    {
        return boundingRect.bottom;
    }

    public float top()
    {
        return boundingRect.top;
    }

    public RectF getBoundingRect()
    {
        return boundingRect;
    }

    public boolean overlaps(float left, float top, float right, float bottom)
    {
        if(right() < left)
        {
            return false;
        }

        if(bottom() < top)
        {
            return false;
        }

        if(left() > right)
        {
            return false;
        }

        if(top() > bottom)
        {
            return false;
        }

        return true;
    }

    public static float distance(float ax, float ay,float bx, float by)
    {
      if (ax < bx)
        return bx - ay;
      else
        return ax - by;
    }


    public Vector2D project(float ax, float ay)
    {
        projVec.x = Float.MAX_VALUE;
        projVec.y = Float.MIN_VALUE;

      for (int i = 0; i < corner.length; ++i)
      {
        float dot = Vector2D.dot(corner[i].x,corner[i].y,ax,ay);

        projVec.x = JMath.min(dot, projVec.x);
        projVec.y = JMath.max(dot, projVec.y);
      }

      return projVec;
    }

    public Vector2D getCorner(int c)
    {
        return corner[c];
    }

    public int getNumCorners()
    {
        return corner.length;
    }

    public static float collisionResponse(OBB2D a, OBB2D b,  Vector2D outNormal) 
    {

        float depth = Float.MAX_VALUE;


        for (int i = 0; i < a.getNumCorners() + b.getNumCorners(); ++i)
        {
            Vector2D edgeA;
            Vector2D edgeB;
            if(i >= a.getNumCorners())
            {
                edgeA = b.getCorner((i + b.getNumCorners() - 1) % b.getNumCorners());
                edgeB = b.getCorner(i % b.getNumCorners());
            }
            else
            {
                edgeA = a.getCorner((i + a.getNumCorners() - 1) % a.getNumCorners());
                edgeB = a.getCorner(i % a.getNumCorners());
            }

             tempNormal.x = edgeB.x -edgeA.x;
             tempNormal.y = edgeB.y - edgeA.y; 


          tempNormal.normalize();


          projAVec.equals(a.project(tempNormal.x,tempNormal.y));
          projBVec.equals(b.project(tempNormal.x,tempNormal.y));

          float distance = OBB2D.distance(projAVec.x, projAVec.y,projBVec.x,projBVec.y);

          if (distance > 0.0f)
          {
            return 0.0f;
          }
          else
          {
            float d = Math.abs(distance);

            if (d < depth)
            {
              depth = d;
              outNormal.equals(tempNormal);
            }
          }
        }

        float dx,dy;
        dx = b.getCenter().x - a.getCenter().x;
        dy = b.getCenter().y - a.getCenter().y;
        float dot = Vector2D.dot(dx,dy,outNormal.x,outNormal.y);
        if(dot > 0)
        {
            outNormal.x = -outNormal.x;
            outNormal.y = -outNormal.y;
        }

        return depth;
    }

    public Vector2D getMoveDeltaVec()
    {
    return deltaVec;
}
};
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-14T07:49:44+00:00Added an answer on June 14, 2026 at 7:49 am

    I’m now just unsure how to compute the point of contact when I hit a
    wall.

    You can represent a wall with a simple plane.

    The OBB-vs-plane intersection test is the simplest separating axis test of them all:

    If two convex objects don’t intersect, then there is a plane where
    the projection of these two objects will not intersect.

    A box intersects plane only if the plane normal forms a separating axis. Compute the projection of the box center and the projected radius (4 dot products and a few adds) and you’re good to go (you also get penetration depth for free).

    The condition looks as follows:

    |d| <= a1|n*A1| + a2|n*A2| + a3|n*A3|

    Here:

    d distance from the center of the box to the plane.

    a1...a3 the extents of the box from the center.

    n normal of the plane

    A1...A3 the x,y,z-axis of the box

    Some pseudocode:

    //Test if OBB b intersects plane p
    int TestOBBPlane(OBB b, Plane p)
    {
       // Compute the projection interval radius of b onto L(t) = b.c + t * p.n
       float r = b.e[0]*Abs(Dot(p.n, b.u[0])) +
          b.e[1]*Abs(Dot(p.n, b.u[1])) +
          b.e[2]*Abs(Dot(p.n, b.u[2]));
    
       // Compute distance of box center from plane
       float s = Dot(p.n, b.c) – p.d;
    
       // Intersection occurs when distance s falls within [-r,+r] interval
       return Abs(s) <= r;
    }
    

    The OBB-vs-OBB intersection test is more complicated.

    Let us refer to this great tutorial:

    In this case we no longer have corresponding separating lines that are
    perpendicular to the separating axes. Instead, we have separating
    planes that separate the bounding volumes (and they are perpendicular
    to their corresponding separating axes).

    In 3D space, each OBB only has 3 unique planes extended by its faces,
    and the separating planes are parallel to these faces. We are
    interested in the separating planes parallel to the faces, but in 3D
    space, the faces are not the only concern. We are also interested in
    the edges. The separating planes of interest are parallel to the faces
    of the boxes, and the separating axes of interest are perpendicular to
    the separating planes. Hence the separating axes of interest are
    perpendicular to the 3 unique faces of each box. Notice these 6
    separating axes of interest correspond to the 6 local (XYZ) axes of
    the two boxes.

    So there are 9 separating axes to consider for edges collision in
    addition to the 6 separating axes we already have found for the faces
    collision. This makes the total number of possible separating axes to
    consider at 15.

    Here are the 15 possible separating axes (L) you will need to test:

    CASE 1:  L = Ax
    CASE 2:  L = Ay
    CASE 3:  L = Az
    CASE 4:  L = Bx
    CASE 5:  L = By
    CASE 6:  L = Bz
    CASE 7:  L = Ax x Bx
    CASE 8:  L = Ax x By
    CASE 9:  L = Ax x Bz
    CASE 10: L = Ay x Bx
    CASE 11: L = Ay x By
    CASE 12: L = Ay x Bz
    CASE 13: L = Az x Bx
    CASE 14: L = Az x By
    CASE 15: L = Az x Bz
    

    Here:

    Ax unit vector representing the x-axis of A

    Ay unit vector representing the y-axis of A

    Az unit vector representing the z-axis of A

    Bx unit vector representing the x-axis of B

    By unit vector representing the y-axis of B

    Bz unit vector representing the z-axis of B

    Now you can see the algorithm behind the OBB-OBB intersection test.

    Let’s jump to the source code:

    2D OBB-OBB: http://www.flipcode.com/archives/2D_OBB_Intersection.shtml

    3D OBB-OBB: http://www.geometrictools.com/LibMathematics/Intersection/Intersection.html

    P.S: This link http://www.realtimerendering.com/intersections.html will be useful to those, who wish to go beyond planes and boxes.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a jquery bug and I've been looking for hours now, I can't
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
link Im having trouble converting the html entites into html characters, (&# 8217;) i
For some reason, after submitting a string like this Jack’s Spindle from a text
this is what i have right now Drawing an RSS feed into the php,
I've got a string that has curly quotes in it. I'd like to replace
I am reading a book about Javascript and jQuery and using one of the
In my XML file chapters tag has more chapter tag.i need to display chapters
I am trying to render a haml file in a javascript response like so:
I would like to run a str_replace or preg_replace which looks for certain words

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.