Null object dimensions
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/07/2012 at 03:07, xxxxxxxx wrote:
Ok, I agree with you. Sorry.
I haven't found another way to do yet. And I don't think there is.-Nik
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/07/2012 at 05:22, xxxxxxxx wrote:
no problem Nick, you gave me the answer I needed
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/07/2012 at 07:45, xxxxxxxx wrote:
I'm afraid it must be done recursively. I've asked the developers to make sure. I'll post my findings.
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 27/07/2012 at 04:57, xxxxxxxx wrote:
FYI, recursive calculation is the "official" way indeed, at least that's what the Coordinate Managers Size+ mode is doing.
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 27/07/2012 at 07:19, xxxxxxxx wrote:
Originally posted by xxxxxxxx
I guess you need to calculate it recursively. Need a hint or a full solution?
-NiklasHey Niklas,
I would like a hint or a solution if you don't mind providing one.
Because in this case I don't really know what you guys mean by the term "recursive".
The definition I know of for that word is calling a function from within the same function. But I don't see how that relates to finding the dimensions of a null.-ScottA
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 27/07/2012 at 07:55, xxxxxxxx wrote:
In this case recursive just means to traverse the given hierarchy. Then you can get the bounding box of each child object and use this to calculate the bounding box of the whole hierarchy.
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 11/09/2012 at 08:42, xxxxxxxx wrote:
I thought it would be far more easy. But the rotation-stuff drives me crazy. I can't get it to work properly.
Could someone please help me on finding the correct algorithm?Here's a small video on what I have achieved so far. As you can hardly see, the rotation is not taken in account correctly.
Here's the C4D File.
Thanks in advance,
Niklas -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 12/09/2012 at 03:13, xxxxxxxx wrote:
You need to bring the min max vectors of each object's bounding into global space. This can be done by multiplying with the global matrix of the object.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 12/09/2012 at 07:18, xxxxxxxx wrote:
Hello Matthias,
thanks for your answer. Hm.. I don't really get it. With the bbmin and bbmax I get two points that
are "spanning" the bounding box of the object. But when those are rotated, other points of the
box might be more outside of it. Hard to express. Maybe this video explains it a little more.I have tested this just for a single box for now. This is the code I used.
def bounding_box(op) : mg = op.GetMg() bb = op.GetRad() * mg mp = op.GetMp() * mg bbmin , bbmax = (mp - bb), (mp + bb) mp = (bbmin + bbmax) * 0.5 bb = bbmax - mp return bb, mp
Thanks,
Niklas -
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