#include "ProxyHeaders.hpp" // //############################################################################ //############################ GroupProxy ############################## //############################################################################ // GroupProxy::ClassData* GroupProxy::DefaultData = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GroupProxy::InitializeClass() { Verify(!DefaultData); DefaultData = new ClassData( GroupProxyClassID, "GroupProxy", ChildProxy::DefaultData ); Register_Object(DefaultData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GroupProxy::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // GroupProxy::GroupProxy( ClassData *class_data, SceneProxy *scene, GroupProxy *parent ): ChildProxy(class_data, scene, parent), activeChildProxies(NULL) { Check_Object(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // GroupProxy::~GroupProxy() { Check_Object(this); Verify(activeChildProxies.IsEmpty()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GroupProxy::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GroupProxy::GetCentroid(Point3D *centroid) { Check_Object(this); Check_Pointer(centroid); // //----------------------------------------------- // If we have no children, just return our origin //----------------------------------------------- // unsigned child_count = GetChildCount(); *centroid = Point3D::Identity; if (!child_count) return; // //-------------------------------------------- // Otherwise, just average our child centroids //-------------------------------------------- // ChildProxy *child = UseFirstChildProxy(); while (child) { Check_Object(child); ChildProxy *next = child->UseNextSiblingProxy(); Point3D local_centroid; child->GetCentroid(&local_centroid); LinearMatrix4D m; child->GetLocalToParent(&m); Point3D world_centroid; world_centroid.Multiply(local_centroid, m); *centroid += world_centroid; child->DetachReference(); child = next; } Verify(!child); *centroid /= static_cast(child_count); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GroupProxy::Recenter() { Check_Object(this); // //------------------------------------------------------------------------- // Now, get our centroid in our mesh space, and recenter the mesh around it // in model space //------------------------------------------------------------------------- // Point3D centroid; GetCentroid(¢roid); if (centroid != Point3D::Identity) { LinearMatrix4D matrix; GetLocalToParent(&matrix); matrix(3,0) += centroid.x; matrix(3,1) += centroid.y; matrix(3,2) += centroid.z; SetLocalToParent(matrix); // //---------------------------------------------------------- // First, allow each child hierarchy to remove redundancies //---------------------------------------------------------- // matrix = LinearMatrix4D::Identity; centroid.Negate(centroid); matrix.BuildTranslation(centroid); unsigned child_count = GetChildCount(); ChildProxy *child = UseFirstChildProxy(); for (unsigned i=0; iUseNextSiblingProxy(); child->TransformLocalToParent(matrix); child->DetachReference(); child = next; } if (child) child->DetachReference(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GroupProxy::SortAndAddPolygons( BinSortProcess *process, Stuff::DynamicArrayOf &polygons ) { Check_Object(this); Check_Object(process); Check_Object(&polygons); Verify(process->binSize > 0); // //--------------------------------------------------------------- // See if we can just directly add these polygons into a new mesh //--------------------------------------------------------------- // unsigned polygon_count = polygons.GetLength(); if (polygon_count <= process->binSize) { Copy_Mesh: PolygonMeshProxy *mesh = AppendNewPolygonMeshProxy(); Check_Object(mesh); mesh->AddPolygons(process, polygons); mesh->DetachReference(); return; } // //--------------------------------- // Make a list of all the centroids //--------------------------------- // DynamicArrayOf centroids(polygon_count); unsigned i; PolygonProxy *polygon; for (i=0; iGetSurfaceAreaAndCentroid(¢roids[i]); if (area > SMALL) centroids[i] /= area; } // //------------------------------------------------------------------------ // Calculate the dividing plane, and if none can be found, don't do nothin //------------------------------------------------------------------------ // Plane plane; if (!plane.ComputeBestDividingPlane(centroids)) goto Copy_Mesh; // //----------------------------------------------------------------------- // Create two new meshes under the group for the mesh to be split up into //----------------------------------------------------------------------- // DynamicArrayOf group_a(polygon_count), group_b(polygon_count); unsigned count_a = 0, count_b = 0; // //------------------------------------------------------------------ // Sort each of the centroids against the plane into one of two bins //------------------------------------------------------------------ // for (i=0; icenter); sphere->radius = -1.0f; ChildProxy *child = UseFirstChildProxy(); while (child) { Check_Object(child); ChildProxy *next = child->UseNextSiblingProxy(); // //---------------------------------------------------------- // Transform's the child's bounding sphere into parent space //---------------------------------------------------------- // LinearMatrix4D child_to_parent; child->GetLocalToParent(&child_to_parent); Sphere child_sphere; child->GetBoundingSphere(&child_sphere); Point3D position; position.Multiply(child_sphere.center, child_to_parent); // //----------------------------------------------------------------- // Now stretch the radius of the bounding sphere so that it totally // includes the child sphere //----------------------------------------------------------------- // position -= sphere->center; Scalar range = position.GetLength() + child_sphere.radius; if (range > sphere->radius) { sphere->radius = range; } child->DetachReference(); child = next; } // //------------------------------------- // Make sure the radius is properly set //------------------------------------- // if (sphere->radius == -1.0f) { sphere->radius = 0.0f; return false; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ChildProxy* GroupProxy::AppendMatchingChildProxy( CopyProcess *process, ChildProxy *child ) { Check_Object(this); Check_Object(process); Check_Object(child); if (child->IsDerivedFrom(PolygonMeshProxy::DefaultData)) { PolygonMeshProxy *proxy = AppendNewPolygonMeshProxy(); Check_Object(proxy); proxy->Copy(process, Cast_Object(PolygonMeshProxy*, child)); return proxy; } else if (child->IsDerivedFrom(GroupProxy::DefaultData)) { GroupProxy *proxy = AppendNewGroupProxy(); Check_Object(proxy); proxy->Copy(process, Cast_Object(GroupProxy*, child)); return proxy; } return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ChildProxy* GroupProxy::InsertMatchingChildProxy( CopyProcess *process, ChildProxy *child, ChildProxy *before ) { Check_Object(this); Check_Object(process); Check_Object(child); Check_Object(before); Verify(before->GetParentGroupProxy() == this); STOP(("Not implemented")); return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GroupProxy::FindNamedChildren( DynamicArrayOf *children, const char* prefix, bool matching ) { Check_Object(this); Check_Object(children); Check_Pointer(prefix); // //---------------------- // Get the prefix length //---------------------- // int size = strlen(prefix); // //--------------------------------- // Find out how many children match //--------------------------------- // unsigned count = 0; ChildProxy *child = UseFirstChildProxy(); while (child) { ChildProxy *next = child->UseNextSiblingProxy(); MString name; if (child->GetName(&name)) { if ((!_strnicmp(name, prefix, size)) == matching) ++count; } child->DetachReference(); child = next; } // //------------------------------------------------------------------------ // Set the array length, and if we have any matching children, fill in the // array with those proxies //------------------------------------------------------------------------ // children->SetLength(count); if (count > 0) { child = UseFirstChildProxy(); count = 0; while (child) { ChildProxy *next = child->UseNextSiblingProxy(); // //----------------------------------------------------------------- // If the child has a name and it matches what we are looking for, // store it in the array and bump the reference count so it doesn't // go away //----------------------------------------------------------------- // MString name; if (child->GetName(&name)) { if ((!_strnicmp(name, prefix, size)) == matching) { (*children)[count++] = child; child->AttachReference(); } } child->DetachReference(); child = next; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GroupProxy::DetachChildProxy(ChildProxy* proxy) { Check_Object(this); activeChildProxies.RemovePlug(proxy); Verify(referenceCount > 1); DetachReference(); }