I read all answers, but it's too difficult for me from polygon to line collision. I've asked just about the AABB to the tilted segment push vector that I can understand.
Push rectangle out of line
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: Push rectangle out of line
Re: Push rectangle out of line
Ok. What i'd try is, in that code, replacing the polygon points with those of a rectangle, like this:
Code: Select all
local rectangleX = 200
local rectangleY = 200
local width = 100
-- X, Y pairs for the 4 clockwise points of a square.
local polygonPoints = {
rectangleX, rectangleY,
rectangleX+width, rectangleY,
rectangleX+width, rectangleY+width,
rectangleX, rectangleY+width,
}
In this case, does the detection work in the way that you're after?
Re: Push rectangle out of line
Here is the solution:
It looks like an easy collision solution with custom shape on the tilted line, but the end of line is not as smooth as I want.
It looks like an easy collision solution with custom shape on the tilted line, but the end of line is not as smooth as I want.
Code: Select all
-- push-rectangle.lua
-- cc0, darkfrei 2023
local pr = {}
function pr.newPolygon (polygon)
if #polygon % 2 ~= 0 then
error('Polygon coordinates are missing a value')
end
local minX, minY = polygon[1], polygon[2]
local maxX, maxY = polygon[1], polygon[2]
for i = 3, #polygon-1, 2 do
minX = math.min (minX, polygon[i])
minY = math.min (minY, polygon[i+1])
maxX = math.max (maxX, polygon[i])
maxY = math.max (maxY, polygon[i+1])
end
for i = 1, #polygon-1, 2 do
polygon[i] = polygon[i] - minX
polygon[i+1] = polygon[i+1] - minY
end
polygon.x = minX
polygon.y = minY
polygon.w = maxX-minX
polygon.h = maxY-minY
return polygon
end
function pr.newline (line)
if #line % 2 ~= 0 then
error('line coordinates are missing a value')
end
local minX, minY = line[1], line[2]
local maxX, maxY = line[1], line[2]
for i = 3, #line-1, 2 do
minX = math.min (minX, line[i])
maxX = math.max (maxX, line[i])
minY = math.min (minY, line[i+1])
maxY = math.max (maxY, line[i+1])
end
line.x, line.y = minX, minY
line.w, line.h = maxX-minX, maxY-minY
return line
end
local function getDot (poly, line)
local px, py = poly.x, poly.y
local x1, y1 = line[1], line[2]
local x2, y2 = line[3], line[4]
local dx = x2 - x1
local dy = y2 - y1
local positiveBiggestDot = 0.0
local negativeBiggestDot = 0.0
local indexPositiveBiggest = nil
local indexNegativeBiggest = nil
for index = 1, #poly-1, 2 do
local vertexVectorX = px+poly[index] - x1
local vertexVectorY = py+poly[index+1] - y1
local dot = -dy*vertexVectorX + dx*vertexVectorY
if dot > 0.0 then
if dot > positiveBiggestDot then
positiveBiggestDot = dot
indexPositiveBiggest = index
end
else
if dot < negativeBiggestDot then
negativeBiggestDot = dot
indexNegativeBiggest = index
end
end
end
if positiveBiggestDot > -negativeBiggestDot then
return negativeBiggestDot, indexPositiveBiggest and indexNegativeBiggest
else
return positiveBiggestDot, indexNegativeBiggest and indexPositiveBiggest
end
end
function pr.collision(poly, line)
local bigdot, index = getDot (poly, line)
if not index then
-- All polygon points are on the same side of the line line, so
-- the line can't possibly cross the polygon.
poly.force = nil
return
end
poly.index = index
local px, py = poly.x+poly[index], poly.y+poly[index+1]
local x1, y1 = line[1], line[2]
local x2, y2 = line[3], line[4]
local dx = x2 - x1
local dy = y2 - y1
local vertexVectorX = px-x1
local vertexVectorY = py - y1
local dot = dx*vertexVectorX + dy*vertexVectorY
local vectorScale = dot / (dx * dx + dy * dy)
local collisionX = x1+dx*vectorScale
local collisionY = y1+dy*vectorScale
poly.force = {
px-poly.x, py-poly.y,
collisionX-poly.x, collisionY-poly.y}
return collisionX-(px), collisionY-(py)
end
function pr.push (poly, line, tx, ty)
if poly.x > line.x+line.w or line.x > poly.x+poly.w
or poly.y > line.y+line.h or line.y > poly.y+poly.h then
-- no collision
poly.collision = false
poly.force = false
return tx, ty
end
local pushX, pushY = pr.collision(poly, line)
if pushX then
tx = poly.x+pushX
ty = poly.y+pushY
end
poly.collision = true
return tx, ty
end
return pr
- Attachments
-
- push-rectangle-01.love
- cc0, no license
- (1.92 KiB) Downloaded 24 times
Re: Push rectangle out of line
Hi Darkfrei,
On my phone right now. I don't know if I understand correct what's going on, but I want to suggest clamping 'vectorScale' to the [0, 1] range, so that if the polygon is beyond the line end or before its beginning, the collision point remains in that extremity and doesn't fly out into the air.
So below this line here...
... you'd add this new line to clamp it:
On my phone right now. I don't know if I understand correct what's going on, but I want to suggest clamping 'vectorScale' to the [0, 1] range, so that if the polygon is beyond the line end or before its beginning, the collision point remains in that extremity and doesn't fly out into the air.
So below this line here...
Code: Select all
local vectorScale = dot / (dx * dx + dy * dy)
Code: Select all
vectorScale = vectorScale > 1.0 and 1.0 or (vectorScale < 0.0 and 0.0 or vectorScale)
Who is online
Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 2 guests