mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-16 22:46:03 +01:00
fix(zones): draw complex polygons properly
convex polygons are split into triangles more simply complex polygons are split into trapezoids and then triangles to be drawn
This commit is contained in:
@@ -1,6 +1,151 @@
|
||||
local glm = require 'glm'
|
||||
local zones = {}
|
||||
|
||||
local function getTriangles(polygon)
|
||||
local X = {}
|
||||
X[1], X[2] = polygon.projectToAxis(polygon, vec(1, 0, 0))
|
||||
|
||||
local points = {}
|
||||
local sides = {}
|
||||
local triangles = {}
|
||||
|
||||
for i = 1, #polygon do
|
||||
sides[i] = {polygon[i], polygon[i + 1] or polygon[1]}
|
||||
points[polygon[i]] = {side = i, intersects = {}, v = polygon[i], uses = 0}
|
||||
end
|
||||
|
||||
for i = 1, #polygon do
|
||||
for j = 1, #X do
|
||||
local extremePoint = vec(X[j], polygon[i].yz)
|
||||
if polygon[i].x ~= extremePoint.x then
|
||||
for l = 1, #polygon do
|
||||
local bool, d, d2 = glm.segment.intersectsSegment(polygon[i], extremePoint, polygon[l], polygon[l + 1] or polygon[1])
|
||||
if d > 0.001 and d < 0.999 and d2 > 0.001 and d2 < 0.999 then
|
||||
local intersect = glm.segment.getPoint(polygon[i], extremePoint, d)
|
||||
local valid = polygon.contains(polygon, (polygon[i] + intersect) / 2)
|
||||
if valid then
|
||||
for m = 1, #polygon do
|
||||
local bool, d, d2 = glm.segment.intersectsSegment(polygon[i], intersect, polygon[m], polygon[m + 1] or polygon[1])
|
||||
if d > 0.001 and d < 0.999 and d2 > 0.001 and d2 < 0.999 then
|
||||
valid = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if valid then
|
||||
points[intersect] = {side = l, vertex = polygon[i], v = intersect, uses = 0}
|
||||
points[polygon[i]].intersects[#points[polygon[i]].intersects + 1] = intersect
|
||||
|
||||
sides[l][#sides[l] + 1] = intersect
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function up(a, b)
|
||||
return a.y > b.y
|
||||
end
|
||||
|
||||
function down(a, b)
|
||||
return a.y < b.y
|
||||
end
|
||||
|
||||
function makeTriangles(t)
|
||||
if t.c and t.d then
|
||||
triangles[#triangles + 1] = {a = t.a, b = t.b, c = t.c}
|
||||
triangles[#triangles + 1] = {a = t.b, b = t.c, c = t.d}
|
||||
for k, v in pairs(t) do
|
||||
points[v].uses += 1
|
||||
end
|
||||
else
|
||||
triangles[#triangles + 1] = {a = t.a, b = t.b or t.c, c = t.d or t.c}
|
||||
for k, v in pairs(t) do
|
||||
points[v].uses += 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, #sides do
|
||||
local side = sides[i]
|
||||
local direction = side[1].y - side[2].y
|
||||
if direction > 0 then
|
||||
direction = up
|
||||
else
|
||||
direction = down
|
||||
end
|
||||
table.sort(side, direction)
|
||||
for j = 1, #side - 1 do
|
||||
local a, b = side[j], side[j + 1]
|
||||
local c = points[a].vertex or points[a].intersects[1]
|
||||
local d = points[b].vertex or points[b].intersects[1]
|
||||
if points[a].uses < 2 then
|
||||
if c and d then
|
||||
if points[c].side ~= points[d].side then
|
||||
local c2
|
||||
if points[a].vertex then
|
||||
if points[a].v == points[c].intersects[1] and points[c].intersects?[2] then
|
||||
c2 = points[c].intersects[2]
|
||||
else
|
||||
c2 = points[c].intersects[1]
|
||||
end
|
||||
else
|
||||
c2 = points[a].intersects[2]
|
||||
end
|
||||
local c2Point = points[c2]
|
||||
if c2Point and c2Point.side == points[d].side then
|
||||
c = c2
|
||||
else
|
||||
if points[b].vertex then
|
||||
if points[b].v == points[d].intersects[1] and points[d].intersects?[2] then
|
||||
d = points[d].intersects[2]
|
||||
elseif b ~= points[d].intersects[1] then
|
||||
d = points[d].intersects[1]
|
||||
end
|
||||
elseif points[b].intersects[2] then
|
||||
d = points[b].intersects[2]
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif c then
|
||||
if points[b].side ~= points[c].side then
|
||||
local c2
|
||||
if points[c].intersects?[2] then
|
||||
c2 = points[c].intersects[2]
|
||||
elseif points[a].intersects?[2] then
|
||||
c2 = points[a].intersects[2]
|
||||
end
|
||||
local c2Point = points[c2]
|
||||
if c2Point then
|
||||
if c2Point.side == points[b].side or (c2Point.side - #sides + 1) == points[b].side then
|
||||
c = c2
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif d then
|
||||
if points[a].side ~= points[d].side then
|
||||
local d2
|
||||
if points[d].intersects?[2] then
|
||||
d2 = points[d].intersects[2]
|
||||
elseif points[b].intersects?[2] then
|
||||
d2 = points[b].intersects[2]
|
||||
end
|
||||
local d2Point = points[d2]
|
||||
if d2Point then
|
||||
if d2Point.side == points[a].side or (d2Point.side - #sides + 1) == points[a].side then
|
||||
d = d2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
makeTriangles({a = a, b = b, c = c, d = d})
|
||||
end
|
||||
end
|
||||
end
|
||||
return triangles
|
||||
end
|
||||
|
||||
local function removeZone(self)
|
||||
zones[self.id] = nil
|
||||
end
|
||||
@@ -9,14 +154,17 @@ local function debug(self)
|
||||
local polygon = self.polygon
|
||||
local polyCount = #self.polygon
|
||||
|
||||
for i = 1, polyCount do
|
||||
if i == polyCount then
|
||||
DrawPoly(polygon[i], polygon[1], self.centroid, 255, 0, 0, 50)
|
||||
DrawPoly(polygon[1], polygon[i], self.centroid, 255, 0, 0, 50)
|
||||
else
|
||||
DrawPoly(polygon[i], polygon[i + 1], self.centroid, 255, 0, 0, 50)
|
||||
DrawPoly(polygon[i + 1], polygon[i], self.centroid, 255, 0, 0, 50)
|
||||
end
|
||||
if polygon.isConvex(polygon) then
|
||||
for i = 2, polyCount - 1 do
|
||||
DrawPoly(polygon[1], polygon[i], polygon[i + 1], 255, 0, 0, 50)
|
||||
DrawPoly(polygon[i], polygon[1], polygon[i + 1], 255, 0, 0, 50)
|
||||
end
|
||||
else
|
||||
self.triangles = self.triangles or getTriangles(polygon)
|
||||
for i = 1, #self.triangles do
|
||||
DrawPoly(self.triangles[i].a, self.triangles[i].b, self.triangles[i].c, 255, 0, 0, 50)
|
||||
DrawPoly(self.triangles[i].b, self.triangles[i].a, self.triangles[i].c, 255, 0, 0, 50)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user