// virtual bool LLCrossParcelFunctor::apply(LLViewerObject* obj) { // Add the root object box. mBoundingBox.addBBoxAgent(LLBBox(obj->getPositionRegion(), obj->getRotationRegion(), obj->getScale() * -0.5f, obj->getScale() * 0.5f).getAxisAligned()); // Extend the bounding box across all the children. LLViewerObject::const_child_list_t children = obj->getChildren(); for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin(); iter != children.end(); iter++) { LLViewerObject* child = *iter; mBoundingBox.addBBoxAgent(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); } bool result = false; LLViewerRegion* region = obj->getRegion(); if (region) { std::vector<LLBBox> boxes; boxes.push_back(mBoundingBox); result = region->objectsCrossParcel(boxes); } return result; }
// the selection bbox isn't axis aligned, so we must construct one // should this be cached in the selection manager? yes. LLBBox get_selection_axis_aligned_bbox() { LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); LLVector3 position = selection_bbox.getPositionAgent(); LLBBox axis_aligned_bbox = LLBBox(position, LLQuaternion(), LLVector3(), LLVector3()); axis_aligned_bbox.addPointLocal(LLVector3()); // cycle over the nodes in selection for (LLObjectSelection::iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->begin(); selection_iter != LLSelectMgr::getInstance()->getSelection()->end(); ++selection_iter) { LLSelectNode *select_node = *selection_iter; if (select_node) { LLViewerObject* object = select_node->getObject(); if (object) { axis_aligned_bbox.addBBoxAgent(object->getBoundingBoxAgent()); } } } return axis_aligned_bbox; }
LLBBox LLRegion::GetBox() const { if(contours.empty()) return LLBBox(); // invalid box if(m_box.GetValid()) return m_box; // there are 3 possible longitude bounds: -180 to 180, 0 to 360, -360 to 0 double minlat = 90, minlon[3] = {180, 360, 0}; double maxlat = -90, maxlon[3] = {-180, 0, -360}; for(std::list<poly_contour>::const_iterator i = contours.begin(); i != contours.end(); i++) { bool neg = false, pos = false; for(poly_contour::const_iterator j = i->begin(); j != i->end(); j++) if(j->x < 0) neg = true; else pos = true; double resolved[3] = {0, 0, 0}; if(neg && !pos) resolved[1] = 360; if(pos && !neg) resolved[2] = -360; for(poly_contour::const_iterator j = i->begin(); j != i->end(); j++) { minlat = wxMin(minlat, j->y); maxlat = wxMax(maxlat, j->y); for(int k = 0; k<3; k++) { minlon[k] = wxMin(minlon[k], j->x + resolved[k]); maxlon[k] = wxMax(maxlon[k], j->x + resolved[k]); } } } double d[3]; for(int k = 0; k<3; k++) { double a = maxlon[k] + minlon[k]; // eliminate cases where the average longitude falls outside of -180 to 180 if(a <= -360 || a >= 360) d[k] = 360; else d[k] = maxlon[k] - minlon[k]; } // find minimum difference (best case to use) double epsilon = 1e-2; // because floating point rounding favor... d1, then d2 then d3 d[1] += epsilon, d[2] += 2*epsilon; int mink = 0; for(int k=1; k<3; k++) if(d[k] < d[mink]) mink = k; LLBBox &box = const_cast<LLBBox&>(m_box); box.Set(minlat, minlon[mink], maxlat, maxlon[mink]); return m_box; }
void object::test<9>() { // // test the addBBoxLocal() method // LLBBox bbox1; bbox1.addBBoxLocal(LLBBox(LLVector3(), LLQuaternion(), LLVector3(0.0f, 0.0f, 0.0f), LLVector3(3.0f, 3.0f, 3.0f))); ensure_equals("addPointLocal center local (3)", bbox1.getCenterLocal(), LLVector3(1.5f, 1.5f, 1.5f)); ensure_equals("addPointLocal min (3)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f)); ensure_equals("addPointLocal max (3)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f)); bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f))); ensure_equals("addPointLocal center local (4)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 5.0f)); ensure_equals("addPointLocal center agent (4)", bbox1.getCenterAgent(), LLVector3(5.0f, 5.0f, 5.0f)); ensure_equals("addPointLocal min (4)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f)); ensure_equals("addPointLocal max (4)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f)); }
void QToolAlign::renderManipulators() { computeManipulatorSize(); LLVector3 bbox_center = mBBox.getCenterAgent(); LLVector3 bbox_scale = mBBox.getMaxLocal() - mBBox.getMinLocal(); for (S32 axis = VX; axis <= VZ; axis++) for (F32 direction = -1.0; direction <= 1.0; direction += 2.0) { F32 size = mManipulatorSize; LLColor4 color = manipulator_color[axis]; if ((axis == mHighlightedAxis) && (direction == mHighlightedDirection)) { size *= 2.0; color *= 1.5; } S32 arrows = 1; if (mForce) { arrows = 2; } for (S32 i = 0; i < arrows; i++) { LLVector3 axis_vector = LLVector3(0,0,0); axis_vector.mV[axis] = direction * (bbox_scale.mV[axis] / 2.0 + i * (size/3.0)); LLVector3 manipulator_center = bbox_center + axis_vector; LLQuaternion manipulator_rotation; manipulator_rotation.shortestArc(LLVector3(0,0,1), -1.0 * axis_vector); LLBBox manipulator_bbox = LLBBox(manipulator_center, manipulator_rotation, LLVector3(), LLVector3()); manipulator_bbox.addPointLocal(LLVector3(-1, -1, -0.75) * size * 0.5); manipulator_bbox.addPointLocal(LLVector3(1, 1, 0.75) * size * 0.5); gGL.color4fv(color.mV); // sadly, gCone doesn't use gGL like gBox does (presumably because its author smokes crack) so we // also set the raw GL color. hopefully this won't screw-up later rendering. glColor4fv(color.mV); render_cone_bbox(manipulator_bbox); } } }
void QToolAlign::renderManipulators() { computeManipulatorSize(); LLVector3 bbox_center = mBBox.getCenterAgent(); LLVector3 bbox_scale = mBBox.getMaxLocal() - mBBox.getMinLocal(); for (S32 axis = VX; axis <= VZ; axis++) for (F32 direction = -1.0; direction <= 1.0; direction += 2.0) { F32 size = mManipulatorSize; LLColor4 color = manipulator_color[axis]; if ((axis == mHighlightedAxis) && (direction == mHighlightedDirection)) { size *= 2.0; color *= 1.5; } S32 arrows = 1; if (mForce) { arrows = 2; } for (S32 i = 0; i < arrows; i++) { LLVector3 axis_vector = LLVector3(0,0,0); axis_vector.mV[axis] = direction * (bbox_scale.mV[axis] / 2.0 + i * (size/3.0)); LLVector3 manipulator_center = bbox_center + axis_vector; LLQuaternion manipulator_rotation; manipulator_rotation.shortestArc(LLVector3(0,0,1), -1.0 * axis_vector); LLBBox manipulator_bbox = LLBBox(manipulator_center, manipulator_rotation, LLVector3(), LLVector3()); manipulator_bbox.addPointLocal(LLVector3(-1, -1, -0.75) * size * 0.5); manipulator_bbox.addPointLocal(LLVector3(1, 1, 0.75) * size * 0.5); gGL.color4fv(color.mV); gGL.color4fv(color.mV); render_cone_bbox(manipulator_bbox); } } }
void object::test<7>() { // // test the getExtentLocal() method // ensure_equals("Default bbox local extent", LLBBox().getExtentLocal(), LLVector3(0.0f, 0.0f, 0.0f)); LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(), LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f)); ensure_equals("Custom bbox extent local", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f)); LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)), LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); ensure_equals("Custom bbox extent local with rot", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f)); }
void object::test<6>() { // // test the getCenterAgent() // ensure_equals("Default bbox agent center", LLBBox().getCenterAgent(), LLVector3(0.0f, 0.0f, 0.0f)); LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(), LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f)); ensure_equals("Custom bbox center agent", bbox1.getCenterAgent(), LLVector3(4.0f, 7.0f, 10.0f)); LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)), LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); ensure("Custom bbox center agent with rot", APPROX_EQUAL(bbox2.getCenterAgent(), LLVector3(-2.0f, 4.0f, 4.0f))); }
void object::test<5>() { // // test the getCenterLocal() method // ensure_equals("Default bbox local center", LLBBox().getCenterLocal(), LLVector3(0.0f, 0.0f, 0.0f)); LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(), LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f)); ensure_equals("Custom bbox center local", bbox1.getCenterLocal(), LLVector3(3.0f, 5.0f, 7.0f)); LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)), LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); ensure_equals("Custom bbox center local with rot", bbox2.getCenterLocal(), LLVector3(3.0f, 3.0f, 3.0f)); }
void object::test<11>() { // // test the addBBoxAgent() method // LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(1.0, 0.0, 0.0, 1.0), LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); bbox1.addPointAgent(LLVector3(1.0f, 1.0f, 1.0f)); bbox1.addPointAgent(LLVector3(3.0f, 3.0f, 3.0f)); bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f))); ensure_equals("addPointAgent center local (2)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 3.0f)); ensure_equals("addPointAgent center agent (2)", bbox1.getCenterAgent(), LLVector3(6.0f, -10.0f, 8.0f)); ensure_equals("addPointAgent min (2)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, -4.0f)); ensure_equals("addPointAgent max (2)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f)); }
void QToolAlign::align() { // no linkset parts, please LLSelectMgr::getInstance()->promoteSelectionToRoot(); std::vector<LLPointer<LLViewerObject> > objects; std::map<LLPointer<LLViewerObject>, LLBBox > original_bboxes; // cycle over the nodes in selection and collect them into an array for (LLObjectSelection::root_iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); selection_iter != LLSelectMgr::getInstance()->getSelection()->root_end(); ++selection_iter) { LLSelectNode *select_node = *selection_iter; if (select_node) { LLViewerObject* object = select_node->getObject(); if (object) { LLVector3 position = object->getPositionAgent(); LLBBox bbox = LLBBox(position, LLQuaternion(), LLVector3(), LLVector3()); bbox.addPointLocal(LLVector3()); // add the parent's bbox bbox.addBBoxAgent(object->getBoundingBoxAgent()); LLViewerObject::const_child_list_t& children = object->getChildren(); for (LLViewerObject::const_child_list_t::const_iterator i = children.begin(); i != children.end(); i++) { // add the child's bbox LLViewerObject* child = *i; bbox.addBBoxAgent(child->getBoundingBoxAgent()); } objects.push_back(object); original_bboxes[object] = bbox; } } } S32 axis = mHighlightedAxis; F32 direction = mHighlightedDirection; // sort them into positional order for proper packing BBoxCompare compare(axis, direction, original_bboxes); sort(objects.begin(), objects.end(), compare); // storage for their new position after alignment - start with original position first std::map<LLPointer<LLViewerObject>, LLBBox > new_bboxes = original_bboxes; // find new positions for (U32 i = 0; i < objects.size(); i++) { LLBBox target_bbox = mBBox; LLVector3 target_corner = target_bbox.getCenterAgent() - direction * target_bbox.getExtentLocal() / 2.0; LLViewerObject* object = objects[i]; LLBBox this_bbox = original_bboxes[object]; LLVector3 this_corner = this_bbox.getCenterAgent() - direction * this_bbox.getExtentLocal() / 2.0; // for packing, we cycle over several possible positions, taking the smallest that does not overlap F32 smallest = direction * 9999999; // 999999 guarenteed not to be the smallest for (U32 j = 0; j <= i; j++) { // how far must it move? LLVector3 delta = target_corner - this_corner; // new position moves only on one axis, please LLVector3 delta_one_axis = LLVector3(0,0,0); delta_one_axis.mV[axis] = delta.mV[axis]; LLVector3 new_position = this_bbox.getCenterAgent() + delta_one_axis; // construct the new bbox LLBBox new_bbox = LLBBox(new_position, LLQuaternion(), LLVector3(), LLVector3()); new_bbox.addPointLocal(this_bbox.getExtentLocal() / 2.0); new_bbox.addPointLocal(-1.0 * this_bbox.getExtentLocal() / 2.0); // check to see if it overlaps the previously placed objects BOOL overlap = FALSE; llwarns << "i=" << i << " j=" << j << llendl; if (!mForce) // well, don't check if in force mode { for (U32 k = 0; k < i; k++) { LLViewerObject* other_object = objects[k]; LLBBox other_bbox = new_bboxes[other_object]; BOOL overlaps_this = bbox_overlap(other_bbox, new_bbox); if (overlaps_this) { llwarns << "overlap" << new_bbox.getCenterAgent() << other_bbox.getCenterAgent() << llendl; llwarns << "extent" << new_bbox.getExtentLocal() << other_bbox.getExtentLocal() << llendl; } overlap = (overlap || overlaps_this); } } if (!overlap) { F32 this_value = (new_bbox.getCenterAgent() - direction * new_bbox.getExtentLocal() / 2.0).mV[axis]; if (direction * this_value < direction * smallest) { smallest = this_value; // store it new_bboxes[object] = new_bbox; } } // update target for next time through the loop if (j < objects.size()) { LLBBox next_bbox = new_bboxes[objects[j]]; target_corner = next_bbox.getCenterAgent() + direction * next_bbox.getExtentLocal() / 2.0; } } } // now move them in (Unsigned not Signed in 2.0) for (U32 i = 0; i < objects.size(); i++) { LLViewerObject* object = objects[i]; LLBBox original_bbox = original_bboxes[object]; LLBBox new_bbox = new_bboxes[object]; LLVector3 delta = new_bbox.getCenterAgent() - original_bbox.getCenterAgent(); LLVector3 original_position = object->getPositionAgent(); LLVector3 new_position = original_position + delta; object->setPosition(new_position); } LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION); }