I've been trying to write a function that when given an entity it will return a bounding box that encompasses that entity and all entities constrained to it. If it's easier to think of this way a bounding box for an entire contraption.
Below is an example of how I'd like the function to be declared, and what it should return.
[lua]
--- Will put credit to the creator of the function here, every time I use it.
function getBoundingBox( ent )
-- Code that works, unlike mine =(
return bboxMins, bboxMaxs, bboxOrigin
end
[/lua]
I'm going to keep trying to make one myself, but I just can't seem to wrap my head around it. So if someone could do this it would be much appreciated.
Well, what you can do is try to figure out the dimensions. You would first need to get each objects bounding box and put it in a table. Then find the furthest left and furthest right part, get the position of the respective outside of their bounding box. Then get the highest and lowest entity, and get the respective top or bottom position of their bounding box. That should give you the points you need to find the size of the bounding box.
[editline]2nd April 2011[/editline]
It may be tricky if the entities rotate, you would have to do this with local vectors and such.
This is the code with my latest try in it and what it does.
[img_thumb]http://cloud.steampowered.com/ugc/578919280527450837/3B7479F68BBBEF967FFBA871A7F31D915C4219C1/[/img_thumb][img_thumb]http://cloud.steampowered.com/ugc/578919280527450358/527E69D33A7A472B85469E0BCD5763EDA360E3AC/[/img_thumb][img_thumb] http://cloud.steampowered.com/ugc/578919280527449885/013BC735BF952DA30D1226ED51B4582E9ED4DB4C/[/img_thumb]
[lua]
function ENT:getBoundingBox( ent )
entTable = {}
bboxMin = ent:LocalToWorld(ent:OBBMins())
bboxMax = ent:LocalToWorld(ent:OBBMaxs())
self:getBoundingBoxIterator(ent, entTable, bboxMin, bboxMax, ent)
print("BBoxMin : " .. tostring(bboxMin))
print("BBoxMax : " .. tostring(bboxMax))
local vecDem = Vector(math.abs(bboxMax.x - bboxMin.x), math.abs(bboxMax.y - bboxMin.y),math.abs(bboxMax.z - bboxMin.z))
print("Dimensions: " .. tostring(vecDem))
return entTable, bboxMin, bboxMax
end
function ENT:getBoundingBoxIterator( ent, entTable, bboxMin, bboxMax, oEnt)
if entTable == nil then
entTable = { ent }
else
table.insert(entTable, ent)
end
local winDistMax = oEnt:GetPos():Distance(bboxMax)
local winDistMin = oEnt:GetPos():Distance(bboxMin)
local pointDistMax = oEnt:GetPos():Distance(ent:LocalToWorld(ent:OBBMaxs()))
local pointDistMin = oEnt:GetPos():Distance(ent:LocalToWorld(ent:OBBMins()))
if pointDistMax > winDistMax then
bboxMax = ent:LocalToWorld(ent:OBBMaxs())
end
if pointDistMin > winDistMin then
bboxMin = ent:LocalToWorld(ent:OBBMins())
end
if constraint.HasConstraints(ent) then
for _, cEnt in pairs(constraint.GetAllConstrainedEntities(ent)) do
if constraint.HasConstraints(cEnt) then
if !table.HasValue(entTable, cEnt) then
self:getBoundingBoxIterator( cEnt, entTable, bboxMin, bboxMax, oEnt)
end
else
table.insert(entTable, cEnt)
end
end
end
return entTable, bboxMin, bboxMax
end
[/lua]
Wouldn't this work?
[lua]
function ENT:GetCompleteBounds(ent)
local e = self
if ent then e = ent end
local bmin = e:OBBMins()
local bmax = e:OBBMaxs()
if constraint.HasConstraints(e) then
for k,v in pairs(constraint.GetAllConstrainedEntities(e)) do
local vbmin, vbmax
if constraint.HasConstraints(v) then
vbmin, vbmax = self:GetCompleteBounds(v)
else
vbmin, vbmax = v:OBBMins(), v:OBBMaxs()
end
if vbmin.x < bmin.x then
bmin.x = vbmin.x
end
if vbmin.y < bmin.y then
bmin.y = vbmin.y
end
if vbmin.z < bmin.z then
bmin.z = vbmin.z
end
if vbmax.x > bmax.x then
bmax.x = vbmax.x
end
if vbmax.y > bmax.y then
bmax.y = vbmax.y
end
if vbmax.z > bmax.z then
bmax.z = vbmax.z
end
end
end
return bmin, bmax
end
[/lua]
I don't know what you want more than the min and max of the bounding entities, but that should make it go through all constraints and make the bounding box for the entire contraption work I hope. I'm kinda tired when I wrote this, but it should work and I hope that it is what you want.
I'll try that now, I had something similar but it didn't work, I'll let you know, thanks.
Thanks again for trying, but that seems to just get the largest bounding box of all the constrained entities, I need a box that encompasses all constrained entities.
[editline]2nd April 2011[/editline]
Here's what I have at the moment, it's a hybrid of what I was doing and what leiftiger posted, it get's really close most of the time.
[lua]
function ENT:getBoundingBox( ent )
print("\n box routine")
entTable = {}
bboxMin = ent:LocalToWorld(ent:OBBMins())
bboxMax = ent:LocalToWorld(ent:OBBMaxs())
print("BBoxMin : " .. tostring(bboxMin))
print("BBoxMax : " .. tostring(bboxMax))
local vecDem = Vector(math.abs(bboxMax.x - bboxMin.x), math.abs(bboxMax.y - bboxMin.y),math.abs(bboxMax.z - bboxMin.z))
print("Dimensions: " .. tostring(vecDem))
entTable, bboxMin, bboxMax = self:getBoundingBoxIterator(ent, entTable, bboxMin, bboxMax, ent)
print("BBoxMin : " .. tostring(bboxMin))
print("BBoxMax : " .. tostring(bboxMax))
vecDem = Vector(math.abs(bboxMax.x - bboxMin.x), math.abs(bboxMax.y - bboxMin.y),math.abs(bboxMax.z - bboxMin.z))
print("Dimensions: " .. tostring(vecDem))
print("box routine end\n")
return entTable, bboxMin, bboxMax
end
function ENT:getBoundingBoxIterator( ent, entTable, bboxMin, bboxMax, oEnt)
if entTable == nil then
entTable = { ent }
else
table.insert(entTable, ent)
end
local eBBmin = ent:LocalToWorld(ent:OBBMins())
local eBBmax = ent:LocalToWorld(ent:OBBMaxs())
if eBBmin.x <= bboxMin.x then bboxMin.x = eBBmin.x end
if eBBmin.y <= bboxMin.y then bboxMin.y = eBBmin.y end
if eBBmin.z <= bboxMin.z then bboxMin.z = eBBmin.z end
if eBBmax.x >= bboxMax.x then bboxMax.x = eBBmax.x end
if eBBmax.y >= bboxMax.y then bboxMax.y = eBBmax.y end
if eBBmax.z >= bboxMax.z then bboxMax.z = eBBmax.z end
if constraint.HasConstraints(ent) then
for _, cEnt in pairs(constraint.GetAllConstrainedEntities(ent)) do
if constraint.HasConstraints(cEnt) then
if !table.HasValue(entTable, cEnt) then
self:getBoundingBoxIterator( cEnt, entTable, bboxMin, bboxMax, oEnt)
end
else
table.insert(entTable, cEnt)
end
eBBmin = cEnt:LocalToWorld(cEnt:OBBMins())
eBBmax = cEnt:LocalToWorld(cEnt:OBBMaxs())
if eBBmin.x <= bboxMin.x then bboxMin.x = eBBmin.x end
if eBBmin.y <= bboxMin.y then bboxMin.y = eBBmin.y end
if eBBmin.z <= bboxMin.z then bboxMin.z = eBBmin.z end
if eBBmax.x >= bboxMax.x then bboxMax.x = eBBmax.x end
if eBBmax.y >= bboxMax.y then bboxMax.y = eBBmax.y end
if eBBmax.z >= bboxMax.z then bboxMax.z = eBBmax.z end
end
end
return entTable, bboxMin, bboxMax
end
[/lua]
Sorry, you need to Log In to post a reply to this thread.