OSG_BASE_DLLMAPPING void extend(BoxVolume &srcVol, const CylinderVolume &vol) { Pnt3f min, max; if((!srcVol.isValid () && !srcVol.isEmpty()) || srcVol.isInfinite() || srcVol.isStatic () ) { return; } if(!vol.isValid()) return; if(srcVol.isEmpty()) { if(vol.isEmpty()) { return; } else { vol .getBounds(min, max); srcVol.setBounds(min, max); return; } } else if(vol.isEmpty()) { return; } vol.getBounds(min, max); srcVol.setBounds(osgMin(min.x(), srcVol.getMin().x()), osgMin(min.y(), srcVol.getMin().y()), osgMin(min.z(), srcVol.getMin().z()), osgMax(max.x(), srcVol.getMax().x()), osgMax(max.y(), srcVol.getMax().y()), osgMax(max.z(), srcVol.getMax().z())); if(vol.isInfinite()) srcVol.setInfinite(true); return; }
UInt32 ParticleBSPTree::doBuild(std::vector<Int32>::iterator begin, std::vector<Int32>::iterator end, UInt32 nodeindex, GeoVectorProperty *pos) { // reached a leaf? if(begin + 1 == end) { _tree[nodeindex].setValue(*begin); return nodeindex + 1; } // find the bounding volume of the group BoxVolume b; Pnt3f p; b.setEmpty(); for(std::vector<Int32>::iterator i = begin; i != end; ++i) { pos->getValue(p,*i); b.extendBy(p); } // find the axis with the longest extension Vec3f d = b.getMax() - b.getMin(); UInt8 axis = ParticleBSPNode::X; Real32 maxval = d[0]; if(d[1] > maxval) { axis = ParticleBSPNode::Y; maxval = d[1]; } if(d[2] > maxval) { axis = ParticleBSPNode::Z; maxval = d[2]; } // sort in that axis ParticleCompare comp(pos, axis); std::sort(begin,end,comp); // find median value std::vector<Int32>::iterator mid = begin + (end - begin) / 2; Pnt3f p2; pos->getValue(p ,*mid); pos->getValue(p2,(*mid)-1); _tree[nodeindex].setSplit(axis, (p[axis] + p2[axis]) / 2.f); return osgMax( doBuild(begin, mid, nodeindex * 2 , pos), doBuild( mid, end, nodeindex * 2 + 1, pos) ); }
OSG_BASE_DLLMAPPING bool intersect(const BoxVolume &box, const SphereVolume &sphere) { // source: // J. Arvo. A simple method for box-sphere intersection testing. // In A. Glassner, editor, Graphics Gems, pp. 335-339, // Academic Press, Boston, MA, 1990 bool retCode; if(box.isEmpty() == true || sphere.isEmpty() == true) { retCode = false; } else if(box.isInfinite() == true || sphere.isInfinite() == true) { retCode = true; } else { Real32 s; Real32 d = 0.f; //find the square of the distance from the sphere to the box for(Int32 i = 0; i < 3; i++) { if(sphere.getCenter()[i] < box.getMin()[i]) { s = sphere.getCenter()[i] - box.getMin()[i]; d += s * s; } else if(sphere.getCenter()[i] > box.getMax()[i]) { s = sphere.getCenter()[i] - box.getMax()[i]; d += s * s; } } retCode = (d <= (sphere.getRadius() * sphere.getRadius())); } return retCode; }
OSG_BASE_DLLMAPPING void extend(BoxVolume &srcVol, const BoxVolume &vol) { if( (!srcVol.isValid () && !srcVol.isEmpty()) || srcVol.isInfinite() || srcVol.isStatic () ) { return; } if(!vol.isValid()) return; if(srcVol.isEmpty()) { if(vol.isEmpty()) { return; } else { srcVol = vol; return; } } else if(vol.isEmpty()) { return; } srcVol.setBounds(osgMin(vol.getMin().x(), srcVol.getMin().x()), osgMin(vol.getMin().y(), srcVol.getMin().y()), osgMin(vol.getMin().z(), srcVol.getMin().z()), osgMax(vol.getMax().x(), srcVol.getMax().x()), osgMax(vol.getMax().y(), srcVol.getMax().y()), osgMax(vol.getMax().z(), srcVol.getMax().z())); if(vol.isInfinite()) srcVol.setInfinite(true); return; }
OSG_BASE_DLLMAPPING bool intersect(const BoxVolume &box1, const BoxVolume &box2) { bool retCode = false; if(box1.isEmpty() == true || box2.isEmpty() == true) { retCode = false; } else if(box1.isInfinite() == true || box2.isInfinite() == true) { retCode = true; } else { retCode = (box1.getMin()[0] <= box2.getMax()[0] && box1.getMax()[0] >= box2.getMin()[0] ) && (box1.getMin()[1] <= box2.getMax()[1] && box1.getMax()[1] >= box2.getMin()[1] ) && (box1.getMin()[2] <= box2.getMax()[2] && box1.getMax()[2] >= box2.getMin()[2] ); } return retCode; }
OSG_BEGIN_NAMESPACE #if 0 /*! Return a sphere containing a given box */ void SphereVolume::circumscribe(const BoxVolume &box) { float radius = 0.5 * (box.getMax() - box.getMin()).length(); Vec3f center; box.getCenter(center); setValue(center, radius); }
OSG_BASE_DLLMAPPING bool intersect(const BoxVolume &box, const CylinderVolume &cylinder) { bool retCode; Pnt3f apos; Vec3f adir; cylinder.getAxis(apos, adir); if(box.isEmpty() == true || cylinder.isEmpty() == true) { retCode = false; } else if(box.isInfinite() == true || cylinder.isInfinite() == true) { retCode = true; } else { Real32 s1 = 0, s2 = 0, s3 = 0, s4 = 0, d = 0, d1 = 0, d2 = 0; Pnt3f c, p, p1, p2; Vec3f u, u1, u2; // find the distance between the min and the max of the box //with the lower point and the upper point of the cylinder respectively s1 = (apos - box.getMin()).length(); s2 = (apos - box.getMax()).length(); s3 = (apos + adir - box.getMin()).length(); s4 = (apos + adir - box.getMax()).length(); //Check the minimum of the above distances if(s1 <= s2) { d1 = s1; p1 = box.getMin(); } else { d1 = s2; p1 = box.getMax(); } if(s3 <= s4) { d2 = s3; p2 = box.getMin(); } else { d2 = s4; p2 = box.getMax(); } //set the value of the vector corresponding to the shortest distance if(d1 <= d2) { d = d1; c = apos; p = p1; } else { d = d2; c = apos + adir; p = p2; } // decompose the vector in u1 and u2 which are parallel and // perpendicular to the cylinder axis respectively u = p - c; u1 = (u[0] * adir[0] + u[1] * adir[1] + u[2] * adir[2]) / (adir.length() * adir.length()) * adir; u2 = u - u1; if(u1.length() <= 10e-6) { retCode = true; } else if(u2.length() <= 10e-6) { retCode = (d <= 10e-6); } else { retCode = (u2.length() <= cylinder.getRadius()); } } return retCode; }