mirror of
https://github.com/Reuh/wirefame.git
synced 2025-10-27 17:49:31 +00:00
Rewrite
This commit is contained in:
parent
b4798c8c16
commit
77cfbaad52
24 changed files with 3033 additions and 1545 deletions
145
math/bs3.lua
Normal file
145
math/bs3.lua
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
--- 3D bounding sphere
|
||||
local bs3
|
||||
|
||||
local v3 = require((...):match("^(.*)bs3$").."v3")
|
||||
|
||||
-- bs3 methods
|
||||
-- Unless specified otherwise, all operations are done in place and do not create a bounding sphere.
|
||||
local bs3_mt = {
|
||||
-- Clone the bounding sphere. Returns a new bounding sphere.
|
||||
clone = function(self)
|
||||
return bs3(self.center:clone(), self.radius)
|
||||
end,
|
||||
|
||||
-- Set bounding sphere
|
||||
set = function(self, center, radius)
|
||||
self.center:set(center)
|
||||
self.radius = radius
|
||||
return self
|
||||
end,
|
||||
|
||||
-- Retrieve center vectors and radius
|
||||
unpack = function(self)
|
||||
return self.center, self.radius
|
||||
end,
|
||||
|
||||
-- Test if the bounding sphere collide with another bounding sphere, bounding box or point
|
||||
collide = function(self, other)
|
||||
if other.radius then -- bs3
|
||||
return (self.center[1] - other.center[1]) * (self.center[1] - other.center[1]) +
|
||||
(self.center[2] - other.center[2]) * (self.center[2] - other.center[2]) +
|
||||
(self.center[3] - other.center[3]) * (self.center[3] - other.center[3])
|
||||
<= (self.radius + other.radius) * (self.radius + other.radius)
|
||||
elseif other.min then -- bb3
|
||||
local x = math.max(other.min[1], math.min(self.center[1], other.max[1]))
|
||||
local y = math.max(other.min[2], math.min(self.center[2], other.max[2]))
|
||||
local z = math.max(other.min[3], math.min(self.center[3], other.max[3]))
|
||||
return (self.center[1] - x) * (self.center[1] - x) +
|
||||
(self.center[2] - y) * (self.center[2] - y) +
|
||||
(self.center[3] - z) * (self.center[3] - z)
|
||||
<= self.radius * self.radius
|
||||
else -- v3
|
||||
return (self.center[1] - other[1]) * (self.center[1] - other[1]) +
|
||||
(self.center[2] - other[2]) * (self.center[2] - other[2]) +
|
||||
(self.center[3] - other[3]) * (self.center[3] - other[3])
|
||||
<= self.radius * self.radius
|
||||
end
|
||||
end,
|
||||
|
||||
-- Extend the bounding sphere by v (number)
|
||||
extend = function(self, v)
|
||||
self.radius = self.radius + v
|
||||
return self
|
||||
end,
|
||||
|
||||
-- Modify the bounding sphere so that it include v (v3 or bs3)
|
||||
include = function(self, v)
|
||||
if v.min then -- bounding sphere
|
||||
self.radius = (self.center:distance(v.center) + self.radius + v.radius) / 2
|
||||
self.center = v.center + (self.center - v.center):normalize() * (self.radius - v.radius)
|
||||
else -- vector
|
||||
self.radius = (self.center:distance(v) + self.radius) / 2
|
||||
self.center = v + (self.center - v):normalize() * self.radius
|
||||
end
|
||||
return self
|
||||
end,
|
||||
|
||||
-- Common operations with vectors. Returns a new bounding box.
|
||||
__sub = function(self, other)
|
||||
return bs3(self.center - other, self.radius)
|
||||
end,
|
||||
__add = function(self, other)
|
||||
return bs3(self.center + other, self.radius)
|
||||
end,
|
||||
__unm = function(self)
|
||||
return bs3(-self.center, self.radius)
|
||||
end,
|
||||
__div = function(self, other)
|
||||
return bs3(self.center, self.radius / other)
|
||||
end,
|
||||
__mul = function(self, other)
|
||||
return bs3(self.center, self.radius * other)
|
||||
end,
|
||||
|
||||
__tostring = function(self)
|
||||
return ("bs3(%s,%s)"):format(self.center, self.radius)
|
||||
end
|
||||
}
|
||||
bs3_mt.__index = bs3_mt
|
||||
|
||||
bs3 = setmetatable({
|
||||
-- Calculate the mesh's bounding sphere. Returns a new bounding sphere.
|
||||
fromMesh = function(mesh, tr)
|
||||
local bs
|
||||
|
||||
-- Get VertexPosition attribute index in vertex data
|
||||
local iposition
|
||||
for i, t in ipairs(mesh:getVertexFormat()) do
|
||||
if t[1] == "VertexPosition" then
|
||||
if t[3] ~= 3 then error("mesh vertices don't have a 3 dimensional position") end
|
||||
iposition = i
|
||||
break
|
||||
end
|
||||
end
|
||||
if not iposition then error("mesh doesn't have VertexPosition attributes") end
|
||||
|
||||
-- Retrieve vertices
|
||||
local vmap = mesh:getVertexMap()
|
||||
if vmap then
|
||||
local min, max = mesh:getDrawRange()
|
||||
if not min then
|
||||
min, max = 1, #vmap
|
||||
end
|
||||
local v = v3(mesh:getVertexAttribute(vmap[min], iposition))
|
||||
if tr then v:transform(tr) end
|
||||
bs = bs3(v:clone(),0)
|
||||
for i=min+1, max do
|
||||
v = v3(mesh:getVertexAttribute(vmap[i], iposition))
|
||||
if tr then v:transform(tr) end
|
||||
bs:include(v)
|
||||
end
|
||||
else
|
||||
local min, max = mesh:getDrawRange()
|
||||
if not min then
|
||||
min, max = 1, mesh:getVertexCount()
|
||||
end
|
||||
local v = v3(mesh:getVertexAttribute(min, iposition))
|
||||
if tr then v:transform(tr) end
|
||||
bs = bs3(v:clone(),0)
|
||||
for i=min+1, max do
|
||||
v = v3(mesh:getVertexAttribute(i, iposition))
|
||||
if tr then v:transform(tr) end
|
||||
bs:include(v)
|
||||
end
|
||||
end
|
||||
|
||||
return bs
|
||||
end
|
||||
}, {
|
||||
-- center will not be copied.
|
||||
__call = function(self, center, radius)
|
||||
return setmetatable({ center = v3(center), radius = radius }, bs3_mt)
|
||||
end
|
||||
})
|
||||
|
||||
return bs3
|
||||
Loading…
Add table
Add a link
Reference in a new issue