Separating Axis Theorem + OpenGL rotation

Hello everybody :slight_smile:

I finally got SAT working but only if I leave out the roation part from OpenGL. My Player object rotates around his own axis


			GL11.glTranslatef(player.x-player.width/2, player.y-player.height/2, 0f);
			GL11.glRotatef(player.angle, 0f, 0f, 1f);
			GL11.glTranslatef(-player.x-player.width/2, -player.y-player.width/2, 0f);

Works great so far. But the collision detection does not recognize that the polygon (trapez) has rotated.
How do I connect my SAT collision detection with the angle my polygon has rotated?

This is how I go forward:

				
player.y += speed * delta * Math.sin(Math.toRadians(player.angle) - Math.PI/2);
player.x += speed * delta * Math.cos(Math.toRadians(player.angle) - Math.PI/2);

I really need your help :slight_smile: thanks in advance

It’s frustrating when you don’t include the code in question. Please, I have no idea what your code looks like, so post it.

Oh I am sorry

This methods are in Polygon

	public boolean collides(Polygon polygon) {
		Dot[] axes = new Dot[polygon.dotCount];
		
		for(int i=0; i < polygon.dotCount; i++) {
			Dot p1 = polygon.getDots()[i];
			Dot p2 = polygon.getDots()[i + 1 == polygon.dotCount ? 0 : i +1];
			
			Dot edge = p1.subtract(p2);
			Dot normal = edge.perp();
			axes[i] = normal;
		}
		
		for(int i=0; i < axes.length; i++) {
			Projection p1 = this.project(axes[i]);
			Projection p2 = polygon.project(axes[i]);
			
			if(!p1.overlap(p2)) {
				return false;
			}
		}
		
		return true;
	}

	public Projection project(Dot axis) {
		float min = axis.dotProd(getDots()[0]);
		float max = min;
		
		for(int i=1; i < getDots().length; i++) {
			float p = axis.dotProd(getDots()[i]);
			
			if(p < min) {
				min = p;
			} else if(p > max) {
				max = p;
			}
		}
		
		return new Projection(min, max);
	}

where Dot is a Vector, I just called it Dot :wink:

Projection.class

public class Projection {
	
	protected float min;
	protected float max;
	
	public Projection(float min, float max) {
		this.min = min;
		this.max = max;
	}
	
	public boolean overlap(Projection proj) {
		boolean temp = true;
		if(min > proj.max || max < proj.min)
			temp = false;
		
		return temp;
	}
}

I hope that was all of the relevant code. Sorry again, I thought that was a common problem.

Your sat code looks good. You maybe checking unrotated polygons though.

Btw, of it’s just obbs you can ditch the check for 2 axes to make it faster still.

Hey thanks for your answer. Only the Player’s polygon is rotated, the other polygons are “normal”. I did not understand your last sentence. What do you mean exactly?

I did not found out something new, but I created a screenshot to visualize my problem. I understand that the collision detection is working, but only internally. What I am rendering is not true!?

Here you are:

please please help meee :point:

What i meant was because you are using an oriented box, you can skip checks for 2 axes since 2 of the edges are parallel to each other.

Okay thanks, but I think I will keep it as it is, I might want to use more than 4 axes later.

Anyone else can help me with the real problem?

Ok I came to the point that rotating the polygons only with openGL is not the right way, because it is just an illusion. The actual verctors aren’t rotated at all.

So here is my code (little different now) with the user input and rotating stuff. What do I have to do? Really I do not come further. I need your help. Getting desperate :’(

hip = forwardSpeed * delta;
		
			float radAng = (float) Math.toRadians(player.angle);
			float cosAngle = (float) Math.cos(radAng);
			float sinAngle = (float) Math.sin(radAng);
			
			
			if(Keyboard.isKeyDown(Keyboard.KEY_W)) {
				player.x += hip * sinAngle;
				player.y += hip * cosAngle;
			}
			
			if(Keyboard.isKeyDown(Keyboard.KEY_S)) {
				hip = backwardSpeed * delta;
				
				player.y -= hip * Math.sin(Math.toRadians(player.angle));
				player.x -= hip * Math.cos(Math.toRadians(player.angle));
			}

You should have another polygon vertex array that is rotated and use that to check for collisions.

you can use:

sin - cos
cos + sin

if I remember correctly.

Or just rotate from origin like what you’re doing, translate and check for collisions. just clear the rotations and translations every frame. slow but should work.

Hey thanks for the answer, could please show me with code or an example? I tried some thing that didn’t work or did the same :smiley:

www.rel.phatcode.net/index.php?action=contents&item=ConvexWars-FB

That’s made in BASIC though.

edit:

I think I have a little demo in c++ here:

www.rel.phatcode.net/junk.php?id=121

/samples

Thanks dude, but the problem was something else :smiley: my method for texture rendering used the normal x and y coords :smiley:

I think I got the right rotation Part, but now it has to be translated that it rotates around its center. In openGl I used this


GL11.glTranslatef(player.x-player.width/2, player.y-player.height/2, 0f);
GL11.glRotatef(player.angle, 0f, 0f, 1f);
GL11.glTranslatef(-player.x-player.width/2, -player.y-player.width/2, 0f);

what would be the equivalent in “plain” java code. I naivle tried this :smiley:

before:
		x -= width/2;
		y -= height/2;

after rotation:
		x -= -width/2;
		y -= -height/2;

I feel a little bit dumb with this try :smiley: Pleaseeeee there is only a little step to success and I can sleep again :point:

this is going to be an one man show, anyway hope is there ::slight_smile:

This is the current rotation at an angle given by the user input (left right key)

this code is doing the rotation…

	
tmpDots[0].set(x * cosAngle - y * sinAngle, x * sinAngle + y * cosAngle);
		tmpDots[1].set(x * cosAngle - (y + height) * sinAngle, x * sinAngle + (y + height) * cosAngle);
		tmpDots[2].set((x + width) * cosAngle - (y + height) * sinAngle, (x + width) * sinAngle + (y + height) * cosAngle);
		tmpDots[3].set((x + width) * cosAngle - y * sinAngle, (x + width) * sinAngle + y * cosAngle);

I saw this behaviour when I only used the glRotatef() method without translating, but in this case I really do not know how to translate it.

I don’t think I understand what you’re saying correctly. Are you tring to orbit your sprite from an arbitrary point or rotate your sprite from its own center.

I think he’s saying the center. Although I have no idea…

Hello,
Yes I want to rotate the pumpkin around it’s center and move it in its new facing direction. I Think it is the same as in GTA I + II. I think it is called Bird’s-eye view. however, there is only missing the translation because it has now a too big rotation radius, and thats completely wrong. I hope you guys understand me better now :smiley:

www.rel.phatcode.net/junk.php?id=140

There’s a sprite rotate scale function in there you could modify. Uses lwjgl.

Hello,

that helped a bit. But I’m stucking again.
The pumpkin is either in the left bottom corner, but rotates the right way. If I add x and y coords it runs faster then the particle effect, which uses only the x and y coords from the pumpkin. It has also the 4 Verctors for the polygon.

		float radAng = (float) Math.toRadians(this.angle);
		float cz = (float) Math.cos(radAng);
		float sz = (float) Math.sin(radAng);
		
		float hx = (width/2);
		float hy = (height/2);
		
		float hx1 = -hx;    // top left
		float hy1 = -hy;
		float hx2 = -hx;	// bottom left
		float hy2 =  hy;
		float hx3 =  hx;	// bottom right
		float hy3 =  hy;
		float hx4 =  hx;	// top right
		float hy4 = -hy;
		
// I added the x and y coords. looked good at first
		float x1 = cz * hx1 - sz * hy1;
		float y1 = sz * hx1 + cz * hy1;
		float x2 = cz * hx2 - sz * hy2;
		float y2 = sz * hx2 + cz * hy2;
		float x3 = cz * hx3 - sz * hy3;
		float y3 = sz * hx3 + cz * hy3;
		float x4 = cz * hx4 - sz * hy4;
		float y4 = sz * hx4 + cz * hy4;

		tmpDots[0].set(x1, y1);
		tmpDots[1].set(x2, y2);
		tmpDots[2].set(x3, y3);
		tmpDots[3].set(x4, y4);

the pumpkin should be where the particle effect is.

any idea? I think I messed up everything by now :frowning:

You forgot to add the translation to you final coordinates. (x,y)