Null object dimensions
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 12/09/2012 at 07:39, xxxxxxxx wrote:
Hi,
here a function I wrote.
Note that it is not recursive - if you have a Null as a child it won't work properly.
What it does is go through every points of every object in the group and save the min and max in global coordinates.# get min and max points of a group in global coordinates def getMinAndMaxPoints(nullObj) : if (nullObj.GetType() != c4d.Onull) : #no group children = [nullObj] else: children = nullObj.GetChildren() groupPos = c4d.Vector(0) groupSize = Vector(0) groupMinPoint = Vector(0) groupMaxPoint = Vector(0) start = True for child in children: mat = child.GetMg() globalPos = mat.off points = child.GetAllPoints() for point in points: #print(point + globalPos) point = point + globalPos if start == True: start = False groupMinPoint = Vector(point) groupMaxPoint = Vector(point) else: if groupMinPoint.x > point.x: groupMinPoint.x = point.x if groupMinPoint.y > point.y: groupMinPoint.y = point.y if groupMinPoint.z > point.z: groupMinPoint.z = point.z if groupMaxPoint.x < point.x: groupMaxPoint.x = point.x if groupMaxPoint.y < point.y: groupMaxPoint.y = point.y if groupMaxPoint.z < point.z: groupMaxPoint.z = point.z #end else #end for points #end for child dico = dict() dico["max"] = groupMaxPoint dico["min"] = groupMinPoint return dico
Alex
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 12/09/2012 at 09:18, xxxxxxxx wrote:
@Al3D: Thanks for your code. But this comes with the huge overhead of iterating over each point of
each object. GetRad() and GetMp() call ObjectData::GetDimension() which does not necessarily iterate
over each point in the mesh. On a cube for example, for GetRad(), it would just return the half of its
size (PRIM_LEN_CUBE) instead of iterating over each point it has generated. Also, when using your
technique, you could easily hit generator objects.I'm so sure there is a better technique, but the only one that comes into my mind is to convert the
bounding-box retrieved by GetRad() and GetMp() into an 8 point cube, multiply each point with the
matrix and then check each point. Is there a better way to do it?Thanks,
Niklas -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 12/09/2012 at 11:09, xxxxxxxx wrote:
csto objs(hierarchy) -> join()
Cheers
Lennart -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 12/09/2012 at 12:03, xxxxxxxx wrote:
@tca: Do you mean for converting the generators?
Well, I actually don't like the idea of using this method at all. In my current project I need to know the
BB size in a Tag. This kinda "brute-force" computation would be done every time the tag was
executed. I could live with that if it would be once or so :X-Nik
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 12/09/2012 at 13:27, xxxxxxxx wrote:
The computation actually is very negligible up to rather decent setups.
One trick is to strip all tags on the returned csto/Cached hierarchy but
variable tags (the invisibles, points etc) before running the join command.
The other to run/store some base check data, like hierarchy count, sum
of vectors or whatever i.e. as well as compare time.Just an idea anyhow, that I use at times anyway
Cheers
Lennart -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 13/09/2012 at 06:20, xxxxxxxx wrote:
Hey guys,
I created a AABBox class for another thread, but expanded it to allow you to add additional objects (cumulative bounding box). It's in C++, but you're welcome to use/convert it if it's any use...
//================================================================================== // AABBox Class - An implementation of an "Axis Aligned Bounding Box" class // // This implementation actually builds a OBB (Oriented Bounding Box) to use as the // source for generating the AABB. // // As implemented, if the object is an instance of a PointObject, it uses the // (Global-space) points of the object as the OBB. // // If it's not a PointObject, it generates a BBox (8-point cube) out of the min/max // extents of the object (again in Global-space) to use as the OBB. // // The class also has provisions for generating a bounding box for a combination of // multiple objects, as well as a simple collision-detection routine. //================================================================================== class AABBox { private: Vector m_bbMin; Vector m_bbMax; Bool m_init; void GetAABBox(BaseObject *op, Vector *pMin, Vector *pMax); public: Vector GetMin(void) { return m_bbMin; } Vector GetMax(void) { return m_bbMax; } Bool CollidesWith(BaseObject *op); void AddObject(BaseObject *op); void Init(BaseObject *op = NULL); AABBox(BaseObject *op); AABBox(void) { m_init = false; } ~AABBox(void) {} }; AABBox::AABBox(BaseObject *op) { this->Init(op); } void AABBox::Init(BaseObject *op) { m_init = false; m_bbMin = Vector(); m_bbMax = Vector(); if( !op ) return; this->GetAABBox(op, &m_bbMin, &m_bbMax); m_init = true; } void AABBox::AddObject(BaseObject *op) { if( !op ) return; if( !m_init ) { this->Init(op); } else { // first store the old values... MinMax mm; mm.Init(m_bbMin); mm.AddPoint(m_bbMax); // then add new object... this->GetAABBox(op, &m_bbMin, &m_bbMax); mm.AddPoint(m_bbMin); mm.AddPoint(m_bbMax); // and determine new extents... m_bbMin = mm.GetMin(); m_bbMax = mm.GetMax(); } } void AABBox::GetAABBox(BaseObject *op, Vector *pMin, Vector *pMax) { Matrix opgm = op->GetMgn(); MinMax mm; //-------------------------------------------------------------------------------------------- // With this implementation, if the BaseObject being passed in is an instance of a PointObject, // then the OBB will be built from the actual Global-space points... this take longer if there // are more than 8 points, but gives a tighter fitting AABBox. If this is too slow, you can // get rid of this top part and just always do 8 points, below. // // to see the difference in using the actual points and the 8 point box, see the image on the // second page of this article: http://www.gamasutra.com/view/feature/3426/when_two_hearts_collide_.php //-------------------------------------------------------------------------------------------- if( op->IsInstanceOf(Opoint) ) { const Vector *pPoints = ToPoint(op)->GetPointR(); LONG i, numPoints = ToPoint(op)->GetPointCount(); mm.Init(); for(i=0; i<numPoints; i++) { mm.AddPoint(*pPoints * opgm); pPoints++; } } else { //-------------------------------------------------------------------------------------------- // ...otherwise, generate an 8 point OBB from the Global-space extent vectors //-------------------------------------------------------------------------------------------- *pMin = op->GetMp() - op->GetRad(); // Bounding-Box minimum extents (Local-space) *pMax = op->GetMp() + op->GetRad(); // Bounding-Box maximum extents (Local-space) // bottom mm.Init(*pMin * opgm); mm.AddPoint(Vector(pMin->x, pMin->y, pMax->z) * opgm); mm.AddPoint(Vector(pMax->x, pMin->y, pMax->z) * opgm); mm.AddPoint(Vector(pMax->x, pMin->y, pMin->z) * opgm); // top mm.AddPoint(*pMax * opgm); mm.AddPoint(Vector(pMax->x, pMax->y, pMin->z) * opgm); mm.AddPoint(Vector(pMin->x, pMax->y, pMin->z) * opgm); mm.AddPoint(Vector(pMin->x, pMax->y, pMax->z) * opgm); } // convert to AABBox (described by min/max extent vectors) *pMin = mm.GetMin(); *pMax = mm.GetMax(); // GePrint(op->GetName()+" bbMin: "+utVecToString(*pMin)+" bbMax: "+utVecToString(*pMax)); } Bool AABBox::CollidesWith(BaseObject *op) { if( !m_init ) return false; Vector bbMin; // Bounding-Box minimum extents Vector bbMax; // Bounding-Box maximum extents this->GetAABBox(op, &bbMin, &bbMax); Bool xlap, ylap, zlap; if( bbMin.x < m_bbMax.x && bbMax.x > m_bbMin.x ) xlap = true; else xlap = false; if( bbMin.y < m_bbMax.y && bbMax.y > m_bbMin.y ) ylap = true; else ylap = false; if( bbMin.z < m_bbMax.z && bbMax.z > m_bbMin.z ) zlap = true; else zlap = false; //================================================================================== // output for testing purposes - delete or comment out it not needed String slap = op->GetName(); slap += " xlap: "; slap += xlap ? "true" : "false"; slap += " ylap: "; slap += ylap ? "true" : "false"; slap += " zlap: "; slap += zlap ? "true" : "false"; slap += " BBox Collision: "; slap += (xlap && ylap && zlap) ? "true" : "false"; GePrint(slap); //================================================================================== return (xlap && ylap && zlap); } //================================================================================== // simple testing routine... builds AABBox from first object in scene (actually, // whatever object you pass to it), then tests for collisions with all other // (root level) objects below it in scene (but doesn't really do anything with // the results) //================================================================================== void BBoxTest(BaseObject *op) { if( op ) { AABBox aabb(op); BaseObject *op2 = op->GetNext(); LONG collisions = 0; while( op2 ) { collisions += aabb.CollidesWith(op2); op2 = op2->GetNext(); } } } //================================================================================== // simple testing routine to recursively walk the heirarchy, adding each object to // the AABBox, to generate a single / cumulative bounding box. //================================================================================== void AccumulateBBox(AABBox *aabb, BaseObject *op) { if( !aabb ) return; while(op) { aabb->AddObject(op); AccumulateBBox(aabb, op->GetDown()); op = op->GetNext(); } }
...I didn't include any code to call the bottom two test routines, but it should be pretty straight-forward. Note that you can also get the min/max vectors from the AABBox (which would be in Global-space).
Cheers.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 13/09/2012 at 06:33, xxxxxxxx wrote:
Giblet, you made my day. Thank you very very much!
I actually need C++, I was just prototyping in Python.-Niklas
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 13/09/2012 at 06:37, xxxxxxxx wrote:
Someone mentioned Generators (and Deformers and such)... I hadn't really looked into that, so you might still need to add code to ctso some objects, etc. Alternatively, you might just doc->Polygonize() first and use that (ctso on the entire doc).
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 14/09/2012 at 08:15, xxxxxxxx wrote:
Hei folks,
in case someone needs it: Here's the working version of the above scene-file using Giblets method (but using GetRad()/GetMp() only!!)
Cheers,
-Niklas -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 14/09/2012 at 11:46, xxxxxxxx wrote:
Thanks - it's neat seeing it (working and) ported to Python :). Did you try the full object point-transform method?
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 14/09/2012 at 12:55, xxxxxxxx wrote:
Did you try the full object point-transform method?
Do you mean calculating the bounding-box of point-objects from its points? No. Because,1. I'm pretty sure GetDimension() does this internally for polygon-objects.
2. For splines, the curves could exceed the bounding box defined only by the points.-Nik
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 14/09/2012 at 13:17, xxxxxxxx wrote:
Originally posted by xxxxxxxx
...1. I'm pretty sure GetDimension() does this internally for polygon-objects.
Hmm...
- Load your scene, delete the 2 cubes.
- Add a "Tube" object.
- Switch to Front view.
- Rotate the Tube 30deg or so clockwise.
- Make it editable (turn it into a Polygon Object).
- Grab a point and (in Move mode), pull the point up (at that angle).
- Observe that the top of the BBox is no longer 'tight' on the object (across the top/right sides).
...doing the point-transform method would tighten that box back up (if you needed that).
-
On 26/06/2015 at 01:43, xxxxxxxx wrote:
Oh i think this would solve my problem with this
https://developers.maxon.net/forum/topic/6903/7745_eventadd-doesnt-update-c4d
Not the topic the solution from NiklasR, but The Python c4d file is 404 missing, here.
Anyhow does somebody have a multiple objects boundingbox Python Script Snippet?
Kind regards
mogh