Java-Gaming.org Hi !
 Featured games (90) games approved by the League of Dukes Games in Showcase (753) Games in Android Showcase (228) games submitted by our members Games in WIP (842) games currently in development
 News: Read the Java Gaming Resources, or peek at the official Java tutorials
 Home Help Search Login Register
Pages: [1]
 ignore  |  Print
 How can I implement camera rotation into my collision detection?  (Read 1448 times) 0 Members and 1 Guest are viewing this topic.
tinfoilboy
 « Posted 2014-08-20 22:34:54 »

I've started to add collision with AABBs, I did this without camera rotation and it worked fine, but now when I added rotation, It broke. I've tried to add the x axis to the detection, but it either teleported me to the end of the level, or crashed the game. I have no idea how to add this and would like some help.

Here is my detection code for the forward direction (left, right, and backward is basically the same)

 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 `float dWithRotX = distance * (float) Math.sin(Math.toRadians(rotationX));float dWithRotZ = distance * (float) Math.cos(Math.toRadians(rotationX));for (int z = (int) (this.position.getZ()); z < (int) (this.position.getZ() + dWithRotZ + boundingDepth); z++){   // The maximum Z for this (poor) raycast.   int maxZ = (int) (this.position.getZ() + distance + boundingDepth) - 1;   // Get a bounding box at the current Z, could be null.   AxisAlignedBoundingBox potentialCollider = Planetary.getPlanetary().currentPlanet.getAABBAt(new Vector3f(Math.abs(this.position.getX()), this.position.getY(), z));   // Create a new bounding box for the camera at this position.   AxisAlignedBoundingBox potentialCameraCollider = new AxisAlignedBoundingBox(this, new Vector3f(this.position.getX(), this.position.getY(), z), boundingWidth, boundingHeight, boundingDepth);   // If the potential collider is not null.   if (potentialCollider != null)   {      // If the potential camera collider collides with the potential collider      if (potentialCameraCollider.intersects(potentialCollider))      {         // Break out of this raycast and don't move.         break;      }      // If we don't collide and we are at the last part of the raycast move the camera and break out of the raycast.      else if (z == maxZ)      {         position.x -= dWithRotX;         position.z += dWithRotZ;         break;      }   }   // If there is no collider at the raycast position, and we are at the last part of the raycast, move the camera and break out of the raycast.   else if (z == maxZ)   {      position.x -= dWithRotX;      position.z += dWithRotZ;      break;   }}`

And here is my AABB class

 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 `public class AxisAlignedBoundingBox{   /**    * The parent of this AABB.    * */   public Object parent = null;    /**    * The minimum X of this collider.    * */   public float minX = 0.0f;   /**    * The minimum Y of this collider.    * */   public float minY = 0.0f;   /**    * The minimum Z of this collider.    * */   public float minZ = 0.0f;   /**    * The maximum X of this collider.    * */   public float maxX = 0.0f;   /**    * The maximum Y of this collider.    * */   public float maxY = 0.0f;   /**    * The maximum Z of this collider.    * */   public float maxZ = 0.0f;   /**    * The width of this collider.    * Stored for reference.    * */   private float width = 0.0f;   /**    * The height of this collider.    * Stored for reference.    * */   private float height = 0.0f;   /**    * The depth of this collider.    * Stored for reference.    * */   private float depth = 0.0f;   public AxisAlignedBoundingBox(Object parent, Vector3f position, float width, float height, float depth)   {      this.parent = parent;      this.minX = position.getX() - width;      this.minY = position.getY() - height;      this.minZ = position.getZ() - depth;      this.maxX = position.getX() + width;      this.maxY = position.getY() + height;      this.maxZ = position.getZ() + depth;      this.width = width;      this.height = height;      this.depth = depth;   }   /**    * Update this bounding box.    * */   public void update()   {      if (parent instanceof Camera)      {         Camera pCamera = (Camera) parent;         this.minX = pCamera.getPosition().getX() - width;         this.minY = pCamera.getPosition().getY() - height;         this.minZ = pCamera.getPosition().getZ() - depth;         this.maxX = pCamera.getPosition().getX() + width;         this.maxY = pCamera.getPosition().getY() + height;         this.maxZ = pCamera.getPosition().getZ() + depth;      }   }   /**    * Check if this Bounding Box intersects with the other bounding box.    * */   public boolean intersects(AxisAlignedBoundingBox boundingBox)   {      return (this.maxX >= boundingBox.minX) && (this.maxY >= boundingBox.minY) && (this.maxZ >= boundingBox.minZ) &&            (this.minX <= boundingBox.maxX) && (this.minY <= boundingBox.maxY) && (this.minZ <= boundingBox.maxZ);   }}`

thedanisaur

JGO Knight

Medals: 59

 « Reply #1 - Posted 2014-08-21 01:06:36 »

Is there any reason you need the camera's bounding box to rotate?

Anyway, imo you should not rotate your simple bounding boxes at all. You should make sure that anyway your object rotates it sits inside its bounding box.

Then you should have another layer of bounding volume to do more complex collision detection (rotated, more accurate, etc.). As for your question I have never bothered rotating my bounding volumes, after the simple test I just see if the triangles on the mesh intersect, not the fastest method.

check this out, it may help:
http://www.gamasutra.com/view/feature/131833/when_two_hearts_collide_.php

Every village needs an idiot
tinfoilboy
 « Reply #2 - Posted 2014-08-21 01:18:31 »

No, I'm not trying to rotate the bounding box, I'm trying to rotate the camera so you can look around and move, but my guess is that when you turn, the poor man's raycast I do gets messed up. Meaning that I can walk through the bounding boxes when looking from a different direction than the one you start with.

 Games published by our own members! Check 'em out!
tinfoilboy
 « Reply #3 - Posted 2014-08-21 01:37:34 »

I wonder if I should make the player's bounding box a sphere, and keep the terrain to AABBs...

SHC
 « Reply #4 - Posted 2014-08-21 02:53:45 »

Camera is only for controlling what is viewed on the screen and from where you look. Collisions should not use the camera, they should be done as they are, camera rotation should not affect collision detection.

tinfoilboy
 « Reply #5 - Posted 2014-08-21 03:01:12 »

Camera is only for controlling what is viewed on the screen and from where you look. Collisions should not use the camera, they should be done as they are, camera rotation should not affect collision detection.

Then how would you implement collision? Most games just use an FPS camera and move it, I know I could create a player class, but that would still require the camera to move it, from what I know.

SHC
 « Reply #6 - Posted 2014-08-21 03:31:47 »

You didn't get the basic idea. Think the scene as empty space. Y is up, X is towards right and Z is coming out towards you (out of monitor, of-course). This space is called as the world space. Now, for the case of objects, every object is composed of vertices. Here the vertices are in the object space, they have position inside relative to the object, and as a whole, they are transformed by scaling, translating, or rotating into the world space.

Think of the camera, as just another object in the world. you can position it anywhere you want, and rotate to change the scene what is viewed when seen through it. Therefore, the camera should not affect the collisions in the world. Usually, you wrap up your objects in a sphere or an aabb and test them for collisions. The shapes you use should also move along with the object, that is, whatever transformation you use, will also apply to the colliding shape (We should only apply transformations like translation and rotation, and not of the camera's of-course).

There, in the world space, you will test your objects for collisions and apply transforms according to your collision response. Only then, you apply the camera to the entire scene and then project it to the screen. Usually, these are only applied in the shader level.

Hope you got it now.

lcass
 « Reply #7 - Posted 2014-08-21 10:59:15 »

So , rotation is a bit iffy with this. The question is what are you rotating are you rotating a sprite that is smaller than a sprite normal size for instance a person texture (someone who is inside the tile whose rotation would not go outside its bounds) or with walls and floor or large square like objects where the length of its diameter is either greater than its width or height. Any object whose diagonal is less than the width of the bounding box is a bit unnecesary , if you wanted to you can using a similar method.
The way I would go about tackling this is firstly translate the bounding box coordinates and rotate , note that I will do this outside of shaders with trigonometry just so its a bit easier to see.
 1  2  3  4  5  6  7  8  9  10  11  12 `double nxa ,nya ,nxb,nyb,nxc,nyc,nxd,nyd = 0;//generate the doubles for the trig      nxa = x * Math.cos(angle) - y * Math.sin(angle);//implement rotation of x returning the new x coordinate assuming that this is the top left of your square.      nya = y * Math.cos(angle) + x * Math.sin(angle);        //calculate the different x positions in a clockwise motion.      nxb = (x + width) * Math.cos(angle) - y * Math.sin(angle);//top right corner      nyb = y * Math.cos(angle) + (x + width) * Math.sin(angle);      //bottom right corner corner      nxc = (x + width) * Math.cos(angle) - (y + height) * Math.sin(angle);      nyc = (y + height) * Math.cos(angle) + (x + width) * Math.sin(angle);      //bottom left corner      nxd = x * Math.cos(angle) - (y + height) * Math.sin(angle);      nyd = (y + height) * Math.cos(angle) + x * Math.sin(angle);`

Thats the rotation done , we now have all the coordinates for each of our corners , this is where the difficult is it sort of turns into pixel perfect collision , this is because you are having to generate an array of all the coordinates on the line , you can check if it has crossed the border between the two with some painful checking code using a mixture of pythag gradients and a lot of calculations per tick. So lets stick with this see where we go, now that we have our new coordinates we can use the information to figure out the gradient and with this we can create a list of points that are on that where we are able to check if its crossed the border.
So to calculate our gradients:
 1  2  3  4 `   ab =(Math.max(nya,nyb) - Math.min(nya, nyb))/ (Math.max(nxa, nxb) - Math.min(nxa, nxb));//basic gradient calculation , using min and max so that our gradient is always positive      bc = (Math.max(nyb,nyc) - Math.min(nyb, nyc))/ (Math.max(nxb, nxc) - Math.min(nxb, nxc));      cd = (Math.max(nyc,nyd) - Math.min(nyc, nyd))/ (Math.max(nxc, nxd) - Math.min(nxc, nxd));      da = (Math.max(nya,nyd) - Math.min(nya, nyd))/ (Math.max(nxa, nxd) - Math.min(nxa, nxd));`

Now we can use my overused friend the for loop to generate our array of points . Because we have used the Math.min and Math.max the function of this is made so much easier because we dont need to bother with all the silly is it a negative gradient.
 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20 `       vertex[] boundries  = new vertex[(int)((Math.max(nya,nyb) - Math.min(nya, nyb)) + (Math.max(nyb,nyc) - Math.min(nyb, nyc)) +(Math.max(nyc,nyd)            - Math.min(nyc, nyd)) +(Math.max(nya,nyd) - Math.min(nya, nyd))) + 1];//make it the length of the entire set of coordinates we will recieve I am sorry for this spaghetti just here                int counter = 0; //store a counter for our position in the boundries array so that we dont have to deal with annoying maths      for(double fx = nxa;fx < nxb;fx++){//For further info on this bit you can add an accuracyfactor variable that means you read through the x values in a double so that you prevent holes         boundries[counter] = new vertex(fx,fx * ab,-1);//im using a 3d vertex here , ill ignore the last value and just put -1         counter++;      }      //simples       for(double fx = nxb;fx < nxc;fx++){         boundries[counter] = new vertex(fx,fx * bc,-1);         counter++;      }      for(double fx = nxc;fx < nxd;fx++){         boundries[counter] = new vertex(fx,fx * cd,-1);         counter++;      }      for(double fx = nxd;fx < nxa;fx++){         boundries[counter] = new vertex(fx,fx * da,-1);         counter++;      }`

Ok so we have filled our array with all the coordinates , fairly simple . But wait , int casting is always dodgy at the best of times , what if there are extra slots in the array? that would require checks in the other class which are just a tad tedious , especially if you are doing it with a thousand objects , so here is the check for those. Note how I added 1 extra slot to the array just in case the casting went wrong in the other direction.
 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21 `//ok so lets say the cast went wrong and we have some null spaces in our array , lets just clean those up quickly and transfer them to a clean array      boolean slotsfree = false;      int actuallength = 0;      for(int i = 0; i < boundries.length;i++){         actuallength++;         if(boundries[i] == null){            slotsfree = true;            break;         }      }      vertex[] newboundries;      if(slotsfree){         newboundries = new vertex[actuallength];         for(int i = 0; i < actuallength;i++){            newboundries[i] = boundries[i];         }         return newboundries;      }      else{         return boundries;      }`

So there it is , the way to do it. I am not sure if it will work as expected it was written as I was writing this so there may be some errors.
Here is the function it is contained in.

 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 `       public vertex[] checkAABB(float x , float y , float width , float height,float angle){      //create a method that has four verticies             //( each corner of your AABB) each respectively named a b c d      double nxa ,nya ,nxb,nyb,nxc,nyc,nxd,nyd = 0;//generate the doubles for the trig      nxa = x * Math.cos(angle) - y * Math.sin(angle);//implement rotation of x returning the new x coordinate assuming that this is the top left of your square.      nya = y * Math.cos(angle) + x * Math.sin(angle);        //calculate the different x positions in a clockwise motion.      nxb = (x + width) * Math.cos(angle) - y * Math.sin(angle);//top right corner      nyb = y * Math.cos(angle) + (x + width) * Math.sin(angle);      //bottom right corner corner      nxc = (x + width) * Math.cos(angle) - (y + height) * Math.sin(angle);      nyc = (y + height) * Math.cos(angle) + (x + width) * Math.sin(angle);      //bottom left corner      nxd = x * Math.cos(angle) - (y + height) * Math.sin(angle);      nyd = (y + height) * Math.cos(angle) + x * Math.sin(angle);      double ab,bc,cd,da = 0;// these are the gradients where ab = A to B      ab =(Math.max(nya,nyb) - Math.min(nya, nyb))/ (Math.max(nxa, nxb) - Math.min(nxa, nxb));//basic gradient calculation , using min and max so that our gradient is always positive      bc = (Math.max(nyb,nyc) - Math.min(nyb, nyc))/ (Math.max(nxb, nxc) - Math.min(nxb, nxc));      cd = (Math.max(nyc,nyd) - Math.min(nyc, nyd))/ (Math.max(nxc, nxd) - Math.min(nxc, nxd));      da = (Math.max(nya,nyd) - Math.min(nya, nyd))/ (Math.max(nxa, nxd) - Math.min(nxa, nxd));      vertex[] boundries  = new vertex[(int)((Math.max(nya,nyb) - Math.min(nya, nyb)) + (Math.max(nyb,nyc) - Math.min(nyb, nyc)) +(Math.max(nyc,nyd)        - Math.min(nyc, nyd)) +(Math.max(nya,nyd) - Math.min(nya, nyd))) + 1];//make it the length of the entire set of coordinates we will recieve I am sorry for this spaghetti just here      int counter = 0; //store a counter for our position in the boundries array so that we dont have to deal with annoying maths      for(double fx = nxa;fx < nxb;fx++){//For further info on this bit you can add an accuracyfactor variable that means you read through the x values in a double so that you prevent holes         boundries[counter] = new vertex(fx,fx * ab,-1);//im using a 3d vertex here , ill ignore the last value and just put -1         counter++;      }      //simples       for(double fx = nxb;fx < nxc;fx++){         boundries[counter] = new vertex(fx,fx * bc,-1);         counter++;      }      for(double fx = nxc;fx < nxd;fx++){         boundries[counter] = new vertex(fx,fx * cd,-1);         counter++;      }      for(double fx = nxd;fx < nxa;fx++){         boundries[counter] = new vertex(fx,fx * da,-1);         counter++;      }      //ok so lets say the cast went wrong and we have some null spaces in our array , lets just clean those up quickly and transfer them to a clean array      boolean slotsfree = false;      int actuallength = 0;      for(int i = 0; i < boundries.length;i++){         actuallength++;         if(boundries[i] == null){            slotsfree = true;            break;         }      }      vertex[] newboundries;      if(slotsfree){         newboundries = new vertex[actuallength];         for(int i = 0; i < actuallength;i++){            newboundries[i] = boundries[i];         }         return newboundries;      }      else{         return boundries;      }         }`

I hope this helps , its a difficult topic and a bit mind boggling when trying to visulaise
Pages: [1]
 ignore  |  Print

 ivj94 (585 views) 2018-03-24 14:47:39 ivj94 (49 views) 2018-03-24 14:46:31 ivj94 (383 views) 2018-03-24 14:43:53 Solater (63 views) 2018-03-17 05:04:08 nelsongames (109 views) 2018-03-05 17:56:34 Gornova (159 views) 2018-03-02 22:15:33 buddyBro (703 views) 2018-02-28 16:59:18 buddyBro (92 views) 2018-02-28 16:45:17 xxMrPHDxx (494 views) 2017-12-31 17:17:51 xxMrPHDxx (734 views) 2017-12-31 17:15:51
 Java Gaming Resourcesby philfrei2017-12-05 19:38:37Java Gaming Resourcesby philfrei2017-12-05 19:37:39Java Gaming Resourcesby philfrei2017-12-05 19:36:10Java Gaming Resourcesby philfrei2017-12-05 19:33:10List of Learning Resourcesby elect2017-03-13 14:05:44List of Learning Resourcesby elect2017-03-13 14:04:45SF/X Librariesby philfrei2017-03-02 08:45:19SF/X Librariesby philfrei2017-03-02 08:44:05
 java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org