diff --git a/imports/zones/client.lua b/imports/zones/client.lua index d5cd1e3..d0f6c01 100644 --- a/imports/zones/client.lua +++ b/imports/zones/client.lua @@ -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