• Get bounding box of all constrained entities
    5 replies, posted
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.