
Advertisement

Content Count
15 
Joined

Last visited
Community Reputation
2 NeutralAbout Bob Dylan

Rank
Member
Personal Information

Interests
Programming
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.

Here is my implementation of SAT, it does not work properly as the title says, in that it quite frequently registers a collision when there is not one, can you check and see if there is anything blatantly wrong with the code? Thanks. I have my own custom vector class, and poly class. normals = self.normals isCollision = [] MTVs = [] for i in other.normals: normals.append(i) for j in normals: selfProj = [] otherProj = [] for k in self.vertices: selfProj.append(j * k) for l in other.vertices: otherProj.append(j * l) minS = min(selfProj) maxS = max(selfProj) minO = min(otherProj) maxO = max(otherProj) if (minS > maxO or minO > maxS): """No collision on THIS axis""" isCollision.append(False) else: isCollision.append(True) MTVmag = min(maxO  minS, maxS  minO) MTV = j * MTVmag MTVs.append(MTV) if (all(x == True for x in isCollision)): vectorMags = [] for m in MTVs: vectorMags.append(m.magSquared) actMTV = MTVs[vectorMags.index(min(vectorMags))] """Finds the MTV with the smallest magnitude""" indexOfNorm = MTVs.index(actMTV) CN = normals[indexOfNorm] """CN = Collision Normal RETURN [CN, 0] for now, the 0 is a placeholder for the collision point""" if(actMTV.y >= 0 and other.pos.y > self.pos.y): self.translate(actMTV * 0.4) other.translate(actMTV * 0.4) return [CN, 0] elif (actMTV.y >= 0 and other.pos.y < self.pos.y): self.translate(actMTV * 0.4) other.translate(actMTV * 0.4) return [CN, 0] elif(actMTV.y <= 0 and other.pos.y > self.pos.y): self.translate(actMTV * 0.4) other.translate(actMTV * 0.4) return [CN, 0] elif (actMTV.y <= 0 and other.pos.y < self.pos.y): self.translate(actMTV * 0.4) other.translate(actMTV * 0.4) return [CN, 0]

CircleCircle impulse resolution not working properly
Bob Dylan replied to Bob Dylan's topic in Math and Physics
Here is the problem, as explicitly as I can describe it: sometimes, when my circles are moving with velocities not perpendicular to the X or Y axes, when they are supposed to collide, they just get stuck in each other. This is not what it would be like in real life, and I know that I am supposed to somehow find the penetration vector of the circles and them move them apart. Now what I want you to do is to tell me how to get the penetration vector and then when to move the circles apart from each other. 
CircleCircle impulse resolution not working properly
Bob Dylan replied to Bob Dylan's topic in Math and Physics
Thanks for your advice, I realise that you do not have much time, but could I trouble you to explain to me when and were you deal with penetration, as I have since got the collision response working with restitution. If you would't mind, could you also explain to me how you would calculate the penetration vector for a circlecircle collision? As at the moment, I am using this code: PD = (self.rad + other.rad) + math.sqrt(centDist) angle = diff.xAxisAngle() PDx = PD * math.cos(math.degrees(angle)) PDy = PD * math.sin(math.degrees(angle)) penetrationVec = Vector(PDx, PDy) dP = penetrationVec.scalarMult(0.5) self.center = (self.center).add(dP) other.center = (other.center).subtract(dP) While it does provide accurate enough collisions, it does however make the circles jump when I represent them on the screen. Thanks again. 
CircleCircle impulse resolution not working properly
Bob Dylan replied to Bob Dylan's topic in Math and Physics
I will take your advice on board when continuing with this simulation. However, if you want to inspect the tutorial I used, it is the following link. https://gamedevelopment.tutsplus.com/tutorials/howtocreateacustom2dphysicsenginethebasicsandimpulseresolutiongamedev6331. 
CircleCircle impulse resolution not working properly
Bob Dylan replied to Bob Dylan's topic in Math and Physics
But there was a rather helpful and indepth tutorial that showed how to deal with it. Through I will follow your suggestion if my approach to change the penetration handling from the collision detection to impulse resolution section of the code and by the way  thanks for all the help and time that you have taken to help me. I'll let you know how it goes (if you care). 
CircleCircle impulse resolution not working properly
Bob Dylan replied to Bob Dylan's topic in Math and Physics
What does that mean? 
CircleCircle impulse resolution not working properly
Bob Dylan replied to Bob Dylan's topic in Math and Physics
Thanks, I think that is what is causing the value of the velocities to be large after impulse resolution. 
CircleCircle impulse resolution not working properly
Bob Dylan replied to Bob Dylan's topic in Math and Physics
Are you supposed to deal with penetration in the collision detection phase, or the impulse resolution phase? I ask this because that might be what is throwing this off, because as soon as they collide, the circles make a large jump, which might be affecting their velocities as i am just approximating velocity as current position  old position divided by the timestep, since my velocity verlet implementation does not deal with veloicty explicitly. 
CircleCircle impulse resolution not working properly
Bob Dylan replied to Bob Dylan's topic in Math and Physics
It definitely is strange, yet what I described is the case. I think the error might be in the way that 1/mass is calculated because changing the mass when defining the particle object has not bearing on the resultant impulse. 
CircleCircle impulse resolution not working properly
Bob Dylan replied to Bob Dylan's topic in Math and Physics
I tried that, yet it has no effect on the values. When displaying the circles on the screen, using pygame module, it showed that after colliding, the circles moved in opposite directions, but with velocities faster than what they collided with. 
CircleCircle impulse resolution not working properly
Bob Dylan replied to Bob Dylan's topic in Math and Physics
Dirk Gregorius, That does not have an effect on the values outputted by the method. 
To calculate the distance between 2 points (x,y) and (a,b). You use Pythagoras' theorem: Distance = sqrt[ (by)^2 + (ax)^2 ]

I am doing a little physics project with circle circle collisions for now, and have tried to do impulse resolution for collisions with 2 circles, using the following code. relativeVelocity = (other.doVerletVelocity()).subtract(self.doVerletVelocity()) normDirecVel = relativeVelocity.dotProduct(collisionNormal) restitution = 1  min(self.restitution, other.restitution) numerator = normDirecVel * restitution impulseScalar = numerator / float(1 / self.mass) + float(1 / other.mass) selfVel = self.doVerletVelocity() otherVel = other.doVerletVelocity() impulse = collisionNormal.scalarMult(impulseScalar) selfDV = impulse.scalarMult(1 / self.mass) otherDV = impulse.scalarMult(1 / other.mass) newSelfVel = selfVel.subtract(selfDV) newOtherVel = otherVel.add(otherDV) self.oldPos = (self.center).subtract(newSelfVel.scalarMult(dt)) other.oldPos = (other.center).subtract(newOtherVel.scalarMult(dt)) The problem seems to be that whatever value I give to self.mass and other.mass, the output stays exactly the same, the values that I used are: center = Vector(0, 0) radius = 1 oldPos = Vector(0, 0) accel = Vector(0, 0) mass = 100 restitution = 0.001 center2 = Vector(0, 3.20) radius2 = 1 oldPos2 = Vector(0, 3.201) accel2 = Vector(0, 1) mass2 = 1 restitution2 = 1 the output was: 0.0 0.0 0.0 2.165000000000114 0.0 0.0 0.0 2.1360000000001174 0.0 0.0 0.0 2.1066000000001206 0.0 0.0 0.0 2.076800000000124 0.0 0.0 0.0 2.046600000000127 0.0 0.0 0.0 2.0160000000001306 0.0 0.0 0.0 1.985000000000134 CIRCLE INTERSECTION 0.0 1.985000000000134 0.0 3.938600000000271 0.0 3.970000000000268 0.0 5.891800000000408 0.0 5.9550000000004015 0.0 7.844600000000544 0.0 7.940000000000535 0.0 9.797000000000681 I changed the values for the masses to make them higher, bu the output still remained the same, if you could get to the bottom of this, it would be much appreciated.
 23 replies

I have a circle class which has the following attributes: center, radius, old position, acceleration, mass, and restitution. I then apply impulse resolution as per this link: https://gamedevelopment.tutsplus.com/tutorials/howtocreateacustom2dphysicsenginethebasicsandimpulseresolutiongamedev6331. Here is the code, implementing that, along with my velocity verlet implementation (this is necessary as it explains why I change the values of the old positions of the circles near the end of the impulseScalar method): def doVerletPosition(self): diffPos = (self.center).subtract(self.oldPos) aggregatePos = diffPos.add(self.center) ATT = (self.accel).scalarMult(dt**2) e = ATT.add(aggregatePos) return e def doVerletVelocity(self): deltaD = ((self.center).subtract(self.oldPos)) return deltaD.scalarMult(1/dt) def impulseScalar(self,other): isCollision = self.collisionDetection(other) collisionNormal = isCollision[0] if(isCollision[1] == True): relativeVelocity = (other.doVerletVelocity()).subtract(self.doVerletVelocity()) normDirecVel = relativeVelocity.dotProduct(collisionNormal) restitution = 1(min(self.restitution,other.restitution)) numerator = restitution * normDirecVel impulseScalar = numerator/(self.invMass + other.invMass) impulse = collisionNormal.scalarMult(impulseScalar) selfVel = (self.doVerletVelocity()) otherVel = other.doVerletVelocity() selfVelDiff = impulse.scalarMult(self.invMass) otherVelDiff = impulse.scalarMult(other.invMass) selfVel = selfVel.subtract(selfVelDiff) otherVel = otherVel.subtract(otherVelDiff) self.oldPos = (self.center).subtract(selfVel) other.oldPos = (other.center).subtract(otherVel) It would help if you accepted the vector methods as correct on face value, and I think that they are named well enough to allow you to figure out what they do, however I can paste them in aswell. My main problem is that when I run this, it registers that a collision has happened, yet the values position of the second circle do not change. How would I go about fixing this, as it seems that I am implementing the calculations correctly. The values of the first and second circle is: center = Vector(0,0) radius = 3 oldPos = Vector(0,0) accel = Vector(0,0) mass = 1 restitution = 0.5 center2 = Vector(0,4.2) radius2 = 1 oldPos2 = Vector(0,4.21) accel2 = Vector(0,1) mass2 = 1 restitution2 = 0.7 What it returns is here: (it returns the position of the centers) 0.0 0.0 0.0 4.1896 0.0 0.0 0.0 4.178800000000001 0.0 0.0 0.0 4.167600000000001 0.0 0.0 0.0 4.1560000000000015 0.0 0.0 0.0 4.144000000000002 0.0 0.0 0.0 4.131600000000002 0.0 0.0 0.0 4.118800000000003 0.0 0.0 0.0 4.1056000000000035 0.0 0.0 0.0 4.092000000000004 0.0 0.0 0.0 4.078000000000005 0.0 0.0 0.0 4.063600000000005 0.0 0.0 0.0 4.048800000000006 0.0 0.0 0.0 4.033600000000007 0.0 0.0 0.0 4.018000000000008 0.0 0.0 0.0 4.002000000000009 0.0 0.0 0.0 3.9856000000000096 INTERSECTION 0.0 0.0 0.0 3.9688000000000105 INTERSECTION 0.0 0.0 0.0 3.9516000000000115 INTERSECTION 0.0 0.0 0.0 3.9340000000000126 So when it prints INTERSECTION, surely, the stationary circle must change position, if the impulseScalar method is correct, (as it seems to be (as it follows what is said on that link). Even if I let it run for longer, the stationary circle still does not move.

I know how to calculate the scalar of the velocity vector after a collision with 2 circles (as per this link: https://gamedevelopment.tutsplus.com/tutorials/howtocreateacustom2dphysicsenginethebasicsandimpulseresolutiongamedev6331) These circles cannot rotate and do not have friction but can have different masses, however I cannot seem to find out any way to find the unit vector that I need to multiply the scalar of velocity by to get the new velocity of the particles after the collision. I also know how to check if 2 circles are colliding. Also, I am only dealing with this in a purely "mathssense" (ie. the circles have a center and a radius), and would like to know how I can represent these circles on the screen in python 3.0. The vector class: class Vector(): def __init__(self,x,y): self.x = x self.y = y def add(self, newVector): return Vector(self.x+newVector.x, self.y+newVector.y) def subtract(self,newVector): return Vector(self.xnewVector.x, self.ynewVector.y) def equals(self, newVector): return Vector(newVector.x,newVector.y) def scalarMult(self, scalar): return Vector(self.x*scalar, self.y*scalar) def dotProduct(self, newVector): return (self.x*newVector.x)+(self.y*newVector.y def distance(self): return math.sqrt((self.x)**2 +(self.y)**2) The circle class: class Particles(): def __init__(self,currentPos, oldPos, accel, dt,mass, center, radius): self.currentPos = currentPos self.oldPos = oldPos self.accel = accel self.dt = dt self.mass = mass self.center = center self.radius = radius def doVerletPosition(currentPos, oldPos, accel, dt): a = currentPos.subtract(oldPos) b = currentPos.add(a) c = accel.scalarMult(dt) d = c.scalarMult(dt) return d.add(b) def doVerletVelocity(currentPos, oldPos, dt): deltaD = (currentPos.subtract(oldPos)) return deltaD.scalarMult(1/dt) def collisionDetection(self, center, radius): xCenter = (self.radius).xComponent() yCenter = (self.radius).yComponent() xOther = radius.xComponent() yOther = radius.yComponent() if ((xCenter  xOther)**2 + (yCenteryOther)**2 < (self.radius + radius)**2): return True else: return False I do know about AABBs, but I am only using around 10 particles for now, and AABBs are not necessary now.

Advertisement