OSG_BASE_DLLMAPPING void extend(BoxVolume &srcVol, const Volume &vol) { const Volume *v = &vol; const BoxVolume *box; #ifndef OSG_2_PREP const DynamicVolume *dynamic = dynamic_cast<const DynamicVolume *>(v); if(dynamic) { v = &(dynamic->getInstance()); } #endif if((box = dynamic_cast<const BoxVolume *>(v))) { OSG::extend(srcVol, *box); } else { BoxVolume localBox; Pnt3f min, max; v->getBounds(min, max); localBox.setBounds(min, max); OSG::extend(srcVol, localBox); } }
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_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); }
/*! \ingroup GrpSystemDrawablesGeometryFunctions Draw the given BoxVolume using direct OpenGL calls. */ OSG_SYSTEMLIB_DLLMAPPING void OSG::drawVolume(const BoxVolume &volume) { Pnt3f min,max; volume.getBounds(min, max); glBegin(GL_LINE_LOOP); glVertex3f(min[0], min[1], min[2]); glVertex3f(max[0], min[1], min[2]); glVertex3f(max[0], max[1], min[2]); glVertex3f(min[0], max[1], min[2]); glVertex3f(min[0], min[1], min[2]); glVertex3f(min[0], min[1], max[2]); glVertex3f(max[0], min[1], max[2]); glVertex3f(max[0], max[1], max[2]); glVertex3f(min[0], max[1], max[2]); glVertex3f(min[0], min[1], max[2]); glEnd(); glBegin(GL_LINES); glVertex3f(min[0], max[1], min[2]); glVertex3f(min[0], max[1], max[2]); glVertex3f(max[0], max[1], min[2]); glVertex3f(max[0], max[1], max[2]); glVertex3f(max[0], min[1], min[2]); glVertex3f(max[0], min[1], max[2]); glEnd(); return; }
Action::ResultE draw(DrawEnv *) { BoxVolume vol; _node->getWorldVolume(vol); Pnt3f Min,Max; vol.getBounds(Min,Max); Real32 Length(1.05f * (Max-Min).maxValue()); drawPhysicsBodyCoordinateSystem(_body, Length); drawPhysicsBodyLinearVelocity(_body, Length); drawPhysicsBodyAngularVelocity(_body, Length); // self-destruct delete this; return Action::Continue; }
void Node::updateVolume(void) { // still valid or static, nothing to do if(_sfVolume.getValue().isValid () == true || _sfVolume.getValue().isStatic() == true || getTravMask() == 0x0000 ) { return; } // be careful to not change the real volume. If two threads // are updating the same aspect this will lead to chaos BoxVolume vol = _sfVolume.getValue(); MFUnrecChildNodePtr::const_iterator cIt = this->getMFChildren()->begin(); MFUnrecChildNodePtr::const_iterator cEnd = this->getMFChildren()->end(); vol.setEmpty(); for(; cIt != cEnd; ++cIt) { if(*cIt != NULL && (*cIt)->getTravMask()) { (*cIt)->updateVolume(); vol.extendBy((*cIt)->getVolume()); } } // test for null core. Shouldn't happen, but just in case... if(getCore() != NULL) { getCore()->adjustVolume(vol); } // don't propagate the static flag from children vol.setStatic(false); editSField(VolumeFieldMask); _sfVolume.setValue(vol); }
// test a single node bool RenderPartition::isVisible(Node *pNode) { if(getFrustumCulling() == false) return true; if(_oDrawEnv.getStatCollector() != NULL) { _oDrawEnv.getStatCollector()->getElem(statCullTestedNodes)->inc(); } // _oDrawEnv.getRTAction()->getStatistics()->getElem(statCullTestedNodes)->inc(); if(pNode->getVolume().isInfinite() == true) return true; BoxVolume vol; pNode->updateVolume(); vol = pNode->getVolume(); vol.transform(topMatrix()); if(_oFrustum.intersect(vol)) { // fprintf(stderr,"%p: node 0x%p vis\n", Thread::getCurrent(), node); return true; } if(_oDrawEnv.getStatCollector() != NULL) { _oDrawEnv.getStatCollector()->getElem(statCulledNodes)->inc(); } // _oDrawEnv.getRTAction()->getStatistics()->getElem(statCulledNodes)->inc(); // fprintf(stderr,"%p: node 0x%p invis\n", Thread::getCurrent(), node); // _frustum.dump(); return false; }
OSG_BASE_DLLMAPPING bool intersect(const BoxVolume &box, const FrustumVolume &frustum) { Pnt3f min, max; box.getBounds(min, max); const Plane *frust = frustum.getPlanes(); // check each point of the box to the 6 planes for(Int32 i = 0; i < 6; i++) { if(frust[i].isOutHalfSpace(min, max)) return false; } return true; }
void Node::getWorldVolume(BoxVolume &result) { Matrix m; if(getParent() != NULL) { getParent()->getToWorld(m); } else { m.setIdentity(); } updateVolume(); result = getVolume(); result.transform(m); }
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; }
bool Line::intersect(const BoxVolume &box, Real &enter, Real &exit ) const { Pnt3r low; Pnt3r high; box.getBounds(low, high); Real r; Real te; Real tl; Real in = 0.f; Real out = Inf; if(_dir[0] > TypeTraits<Real>::getDefaultEps()) { r = 1.f / _dir[0]; te = (low [0] - _pos[0]) * r; tl = (high[0] - _pos[0]) * r; if(tl < out) out = tl; if(te > in) in = te; } else if(_dir[0] < -TypeTraits<Real>::getDefaultEps()) { r = 1.f / _dir[0]; te = (high[0] - _pos[0]) * r; tl = (low [0] - _pos[0]) * r; if(tl < out) out = tl; if(te > in) in = te; } else if(_pos[0] < low[0] || _pos[0] > high[0]) { return false; } if(_dir[1] > TypeTraits<Real>::getDefaultEps()) { r = 1.f / _dir[1]; te = (low [1] - _pos[1]) * r; tl = (high[1] - _pos[1]) * r; if(tl < out) out = tl; if(te > in) in = te; if(in-out >= TypeTraits<Real>::getDefaultEps()) return false; } else if(_dir[1] < -TypeTraits<Real>::getDefaultEps()) { r = 1.f / _dir[1]; te = (high[1] - _pos[1]) * r; tl = (low [1] - _pos[1]) * r; if(tl < out) out = tl; if(te > in) in = te; if(in-out >= TypeTraits<Real>::getDefaultEps()) return false; } else if(_pos[1] < low[1] || _pos[1] > high[1]) { return false; } if(_dir[2] > TypeTraits<Real>::getDefaultEps()) { r = 1.f / _dir[2]; te = (low [2] - _pos[2]) * r; tl = (high[2] - _pos[2]) * r; if(tl < out) out = tl; if(te > in) in = te; } else if(_dir[2] < -TypeTraits<Real>::getDefaultEps()) { r = 1.f / _dir[2]; te = (high[2] - _pos[2]) * r; tl = (low [2] - _pos[2]) * r; if(tl < out) out = tl; if(te > in) in = te; } else if(_pos[2] < low[2] || _pos[2] > high[2]) { return false; } enter = in; exit = out; // Eps: count flat boxes as intersected // BUGFIXED, was: // return enter-exit < Eps; // This got unstable with bbox check of huge planes // and if compiled as opt lib (at least with my gcc 4.0.2). // However it worked when compiled as dbg lib. // And now something completely different... return in-out < TypeTraits<Real>::getDefaultEps(); // To get you even more confused: It also works if you leave it // as "enter-exit" but declare in/out as Real64. // Now think about it......and if it is not 42, please tell! }
void SortLastWindow::collectDrawables(Node * const node, DrawableListT &drawables) { Material *mat = NULL; NodeCore *core = node->getCore(); if(core != NULL) { // handle material groups MaterialGroup *matGrp = dynamic_cast<MaterialGroup *>(core); if(matGrp != NULL) { mat = matGrp->getMaterial(); // ignore transparent material groups if(mat != NULL && mat->isTransparent()) return; } // handle geometries Geometry *geo = dynamic_cast<Geometry *>(core); if(geo != NULL) { mat = geo->getMaterial(); // ignore transparent materials if(mat == NULL || mat->isTransparent() == false) { DrawableInfo drawableInfo; drawableInfo.node = node; // get transformed volume node->updateVolume(); BoxVolume volume; node->getWorldVolume(volume); // get min,max volume.getBounds(drawableInfo.bMin, drawableInfo.bMax); // num of indices drawableInfo.load = 0; GeoIntegralProperty *indicesPtr = geo->getIndex(Geometry::PositionsIndex); if(indicesPtr != NULL) drawableInfo.load = indicesPtr->size(); // put to list drawables.push_back(drawableInfo); } } // handle poxy groups ProxyGroup *proxy = dynamic_cast<ProxyGroup *>(core); if(proxy != NULL) { DrawableInfo drawableInfo; drawableInfo.node = node; // get transformed volume node->updateVolume(); BoxVolume volume; node->getWorldVolume(volume); // get min,max volume.getBounds(drawableInfo.bMin, drawableInfo.bMax); // num of indices drawableInfo.load = proxy->getIndices(); // put to list drawables.push_back(drawableInfo); } } MFUnrecChildNodePtr::const_iterator nI; for( nI = node->getMFChildren()->begin(); nI != node->getMFChildren()->end(); ++nI) { collectDrawables(*nI, drawables); } }
void selectedNodeChanged(void) { _mgr->setHighlight(_SelectedNode); //Update Details Panel if(_SelectedNode == NULL) { _NodeNameValueLabel->setText(""); _NodeCoreTypeValueLabel->setText(""); _NodeMinValueLabel->setText(""); _NodeMaxValueLabel->setText(""); _NodeCenterValueLabel->setText(""); _NodeTriCountValueLabel->setText(""); _NodeTravMaskValueLabel->setText(""); } else { const Char8 *NodeName = getName(_SelectedNode); if(NodeName == NULL) { _NodeNameValueLabel->setText("Unnamed Node"); } else { _NodeNameValueLabel->setText(NodeName); } _NodeCoreTypeValueLabel->setText(_SelectedNode->getCore()->getType().getCName()); BoxVolume DyVol; _SelectedNode->getWorldVolume(DyVol); Pnt3f Min,Max,Center; DyVol.getBounds(Min,Max); DyVol.getCenter(Center); std::string TempText(""); TempText = boost::lexical_cast<std::string>(Min.x()) + ", " +boost::lexical_cast<std::string>(Min.x()) + ", " + boost::lexical_cast<std::string>(Min.x()); _NodeMinValueLabel->setText(TempText); TempText = boost::lexical_cast<std::string>(Max.x()) + ", " +boost::lexical_cast<std::string>(Max.x()) + ", " + boost::lexical_cast<std::string>(Max.x()); _NodeMaxValueLabel->setText(TempText); TempText = boost::lexical_cast<std::string>(Center.x()) + ", " +boost::lexical_cast<std::string>(Center.x()) + ", " + boost::lexical_cast<std::string>(Center.x()); _NodeCenterValueLabel->setText(TempText); _NodeTravMaskValueLabel->setText(boost::lexical_cast<std::string>(_SelectedNode->getTravMask())); //Tri Cound TriCountGraphOpRefPtr TheTriGraphOp = TriCountGraphOp::create(); TheTriGraphOp->traverse(_SelectedNode); _NodeTriCountValueLabel->setText(boost::lexical_cast<std::string>(TheTriGraphOp->getNumTri())); } }
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; }
// visibility levels bool RenderPartition::pushVisibility(Node * const pNode) { if(getFrustumCulling() == false) return true; FrustumVolume::PlaneSet inplanes = _visibilityStack.back(); if(inplanes == FrustumVolume::P_ALL) { _visibilityStack.push_back(inplanes); return true; } Color3f col; bool result = true; FrustumVolume frustum = _oFrustum; BoxVolume vol = pNode->getVolume(); // don't mess with infinite volumes if(vol.isInfinite() == false) { pNode->updateVolume(); vol = pNode->getVolume(); #if 1 vol.transform(topMatrix()); #else // not quite working Matrix m = topMatrix(); m.invert(); frustum.transform(m); #endif } if(_oDrawEnv.getStatCollector() != NULL) { _oDrawEnv.getStatCollector()->getElem(statCullTestedNodes)->inc(); } if(intersect(frustum, vol, inplanes) == false) { result = false; col.setValuesRGB(1,0,0); if(_oDrawEnv.getStatCollector() != NULL) { _oDrawEnv.getStatCollector()->getElem(statCulledNodes)->inc(); } } else { if(inplanes == FrustumVolume::P_ALL) { col.setValuesRGB(0,1,0); } else { col.setValuesRGB(0,0,1); } } if(getVolumeDrawing()) { dropVolume(this, pNode, col); } _visibilityStack.push_back(inplanes); return result; }
void SortLastWindow::splitDrawables(DrawableListT &src, UInt32 groups, bool cut) { BoxVolume vol; // Real32 srcLoad=0; Real32 dst1Load = 0; Real32 dst2Load = 0; DrawableListT::iterator dI; UInt32 dIFront = 0; UInt32 dIBack = 0; UInt32 axis = 0; Vec3f size; DrawableListT dst1; DrawableListT dst2; UInt32 groups1 = 0; UInt32 groups2 = 0; // no group if(groups == 0) return; // only one group if(groups == 1) { editMFGroupLengths()->push_back(UInt32(src.size())); for(dI = src.begin() ; dI != src.end() ; ++dI) { pushToGroupNodes(dI->node); // srcLoad+=dI->load; } // printf("load:%f\n",srcLoad); return; } groups1 = groups / 2; groups2 = groups - groups1; // collect all load and get summed volume for(dI = src.begin() ; dI != src.end() ; ++dI) { vol.extendBy(dI->bMin); vol.extendBy(dI->bMax); } // get longes axis vol.getSize(size); if(size[0] > size[1]) { if(size[0] > size[2]) axis=0; else axis=2; } else { if(size[1] > size[2]) axis=1; else axis=2; } // sort by volume if(axis == 0) { std::sort(src.begin(),src.end(), DrawableInfo::MaxXOrder()); } else { if(axis == 1) std::sort(src.begin(),src.end(), DrawableInfo::MaxYOrder()); else std::sort(src.begin(),src.end(), DrawableInfo::MaxZOrder()); } // split group if(src.size()) { dIFront = 0; dIBack = UInt32(src.size()) - 1; do { // printf("f %d b %d\n",dIFront,dIBack); if(dst2Load < dst1Load) { dst2.push_back(src[dIBack]); dst2Load += src[dIBack].load*groups/Real32(groups2); dIBack--; } else { dst1.push_back(src[dIFront]); dst1Load += src[dIFront].load*groups/Real32(groups1); dIFront++; } } while(dIFront <= dIBack); } // recourse splitDrawables(dst1, groups1, cut); splitDrawables(dst2, groups2, cut); }
OSG_BASE_DLLMAPPING void extend(SphereVolume &srcVol, const BoxVolume &vol) { Pnt3f min, max, min1, max1, c; Real32 r; BoxVolume vol1; vol.getBounds(min, max); if((!srcVol.isValid () && !srcVol.isEmpty()) || srcVol.isInfinite() || srcVol.isStatic () ) { return; } if(!vol.isValid()) return; if(srcVol.isEmpty()) { if(vol.isEmpty()) { return; } else { c = Pnt3f((min.x() + max.x()) * 0.5f, (min.y() + max.y()) * 0.5f, (min.z() + max.z()) * 0.5f); r = ((max - min).length()) / 2; srcVol.setValue(c, r); return; } } else if(vol.isEmpty()) { return; } srcVol.getBounds(min1, max1); vol1.setBounds(osgMin(min.x(), min1.x()), osgMin(min.y(), min1.y()), osgMin(min.z(), min1.z()), osgMax(max.x(), max1.x()), osgMax(max.y(), max1.y()), osgMax(max.z(), max1.z())); vol1.getBounds(min, max); c = Pnt3f((min.x() + max.x()) * 0.5f, (min.y() + max.y()) * 0.5f, (min.z() + max.z()) * 0.5f); r = ((max - min).length()) / 2; srcVol.setValue(c, r); return; }
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 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; }
ActionBase::ResultE CubeMapGenerator::renderEnter(Action *action) { static Matrix transforms[] = { Matrix( 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1), Matrix(-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1), Matrix( 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1), Matrix( 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1), Matrix( 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1), Matrix( 0, 0, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1) }; RenderAction *a = dynamic_cast<RenderAction *>(action); Action::ResultE returnValue = Action::Continue; Background *pBack = a->getBackground(); Viewport *pPort = a->getViewport(); Node *pActNode = a->getActNode(); CubeMapGeneratorStageData *pData = a->getData<CubeMapGeneratorStageData *>(_iDataSlotId); if(pData == NULL) { pData = this->initData(a); } TraversalValidator::ValidationStatus eStatus = this->validateOnEnter(a); if(eStatus == TraversalValidator::Run) { this->beginPartitionGroup(a); { FrameBufferObject *pTarget = this->getRenderTarget(); if(pTarget == NULL) { pTarget = pData->getRenderTarget(); } Pnt3f oOrigin; if(this->getOriginMode() == CubeMapGenerator::UseStoredValue) { oOrigin = this->getOrigin(); } else if(this->getOriginMode() == CubeMapGenerator::UseBeacon) { fprintf(stderr, "CubemapGen::UseBeacon NYI\n"); } else if(this->getOriginMode() == CubeMapGenerator::UseCurrentVolumeCenter) { BoxVolume oWorldVol; commitChanges(); pActNode->updateVolume(); pActNode->getWorldVolume(oWorldVol); oWorldVol.getCenter(oOrigin); } else if(this->getOriginMode() == CubeMapGenerator::UseParentsVolumeCenter) { fprintf(stderr, "CubemapGen::UseParentsCenter NYI\n"); } Camera *pCam = pData->getCamera(); pActNode->setTravMask(0); for(UInt32 i = 0; i < 6; ++i) { this->pushPartition(a); { RenderPartition *pPart = a->getActivePartition(); pPart->setVolumeDrawing(false); pPart->setRenderTarget(pTarget ); pPart->setWindow (a->getWindow()); pPart->calcViewportDimension(0, 0, 1, 1, this->getWidth (), this->getHeight()); Matrix m, t; // set the projection pCam->getProjection (m, pPart->getViewportWidth (), pPart->getViewportHeight()); pCam->getProjectionTranslation(t, pPart->getViewportWidth (), pPart->getViewportHeight()); pPart->setupProjection(m, t); m = transforms[i]; m[3][0] = oOrigin[0]; m[3][1] = oOrigin[1]; m[3][2] = oOrigin[2]; m.invert(); pPart->setupViewing(m); pPart->setNear (pCam->getNear()); pPart->setFar (pCam->getFar ()); pPart->calcFrustum(); if(this->getBackground() == NULL) { pPart->setBackground(pBack); } else { pPart->setBackground(this->getBackground()); } if(this->getRoot() != NULL) { this->recurse(a, this->getRoot()); } else { this->recurse(a, pPort->getRoot()); } pPart->setDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + i); #ifdef OSG_DEBUGX std::string szMessage("CubeX\n"); pPart->setDebugString(szMessage ); #endif } this->popPartition(a); } pActNode->setTravMask(~0); } this->endPartitionGroup(a); } OSG_ASSERT(pActNode == a->getActNode()); returnValue = Inherited::renderEnter(action); action->useNodeList(false); return returnValue; }
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; }
int main (int argc, char **argv) { Real32 ent, ex; int i; //Lines: const int nlines = 10; Line lines[nlines]; Pnt3f pnts[nlines * 2] = { Pnt3f(0,0,0), Pnt3f(0,1,0), Pnt3f(0,0,0), Pnt3f(2,1,0), Pnt3f(2,0,0), Pnt3f(2,1,0), Pnt3f(-2,0,0), Pnt3f(0,2,0), Pnt3f(-4,2,0), Pnt3f(0,2,0), Pnt3f(-3,0,0), Pnt3f(-2,1,0), Pnt3f(3,4,0), Pnt3f(1,3,0), Pnt3f(-1,0,0), Pnt3f(-1,1,0), Pnt3f(-4,0,0), Pnt3f(-3,1,0), Pnt3f(-4,6,0), Pnt3f(0,6,0) }; for ( i = 0; i < nlines; i++ ) lines[i].setValue( pnts[i*2], pnts[i*2+1] ); BoxVolume b; float xmin, ymin, zmin, xmax, ymax, zmax; xmin = 0; ymin = 0.5; zmin = 0; xmax = 1; ymax = .5; zmax = 1; b.setBounds(xmin, ymin, zmin, xmax, ymax, zmax); std::cout << std::endl; b.dump(); std::cout << std::endl; for ( i = 0 ; i < nlines; i++ ) { std::cout << "Line: (" << lines[i].getPosition() << ") (" << lines[i].getDirection() << ")" << std::endl; bool res = lines[i].intersect( b, ent, ex ); Pnt3f ep = lines[i].getPosition() + ent * lines[i].getDirection(), xp = lines[i].getPosition() + ex * lines[i].getDirection(); std::cout << "Result: " << res; if ( res ) { std::cout << " enter " << ent << "=(" << ep << ") "; bool es = ( b.isOnSurface( ep ) || b.intersect( ep ) ), xs = b.isOnSurface( xp ); if ( ( res && es ) || !res ) std::cout << "ok"; else std::cout << "**BAD**"; std::cout << "; exit " << ex << "=(" << xp << ") "; if ( ( res && xs ) || !res ) std::cout << "ok"; else std::cout << "**BAD**"; } std::cout << std::endl; } return 0; SphereVolume s; float radius; Vec3f center; center[0] = 0; center[1] = 0; center[2] = 0; radius = 1; s.setCenter(center); s.setRadius(radius); std::cout << std::endl; s.dump(); std::cout << std::endl; for ( i = 0 ; i < nlines; i++ ) { std::cout << "Line: (" << lines[i].getPosition() << ") (" << lines[i].getDirection() << ")" << std::endl; bool res = lines[i].intersect( s, ent, ex ); Pnt3f ep = lines[i].getPosition() + ent * lines[i].getDirection(), xp = lines[i].getPosition() + ex * lines[i].getDirection(); std::cout << "Result: " << res; if ( res ) { std::cout << " enter " << ent << "=(" << ep << ") "; bool es = ( s.isOnSurface( ep ) || s.intersect( ep ) ), xs = s.isOnSurface( xp ); if ( ( res && es ) || !res ) std::cout << "ok"; else std::cout << "**BAD**"; std::cout << "; exit " << ex << "=(" << xp << ") "; if ( ( res && xs ) || !res ) std::cout << "ok"; else std::cout << "**BAD**"; } std::cout << std::endl; } // Intersect the line with a cylinder. Pnt3f p; Vec3f d; float rad; p[0] = 0; p[1] = 1; p[2] = 0; d[0] = 0; d[1] = 4; d[2] = 0; rad = 2; CylinderVolume c; c.setValue(p, d, rad); // c.setAxis(p, d); // c.setRadius(rad); std::cout << std::endl; c.dump(); std::cout << std::endl; for ( i = 0 ; i < nlines; i++ ) { std::cout << "Line: (" << lines[i].getPosition() << ") (" << lines[i].getDirection() << ")" << std::endl; bool res = lines[i].intersect( c, ent, ex ); Pnt3f ep = lines[i].getPosition() + ent * lines[i].getDirection(), xp = lines[i].getPosition() + ex * lines[i].getDirection(); std::cout << "Result: " << res; if ( res ) { std::cout << " enter " << ent << "=(" << ep << ") "; bool es = ( c.isOnSurface( ep ) || c.intersect( ep ) ), xs = c.isOnSurface( xp ); if ( ( res && es ) || !res ) std::cout << "ok"; else std::cout << "**BAD**"; std::cout << "; exit " << ex << "=(" << xp << ") "; if ( ( res && xs ) || !res ) std::cout << "ok"; else std::cout << "**BAD**"; } std::cout << std::endl; } //### volume intersection ############################################## std::cout << "### volume intersection test ###" << std::endl; BoxVolume box(-1,-1,-1,1,1,1); BoxVolume boxOut (5,5,5,10,10,10); BoxVolume boxIn(-1,-1,-1,2,2,2); SphereVolume sphere(Pnt3f(0,0,0),2); SphereVolume sphereOut(Pnt3f(2,2,2),1); SphereVolume sphereIn(Pnt3f(1,0,0),1); CylinderVolume cylinder(Pnt3f(0,0,0),Vec3f(1,1,1),1); CylinderVolume cylinderOut(Pnt3f(0,9,9),Vec3f(0,0,1),1); CylinderVolume cylinderIn(Pnt3f(1,0,0),Vec3f(0,1,0),1); // Frustum defined by normal vector and distance Plane pnear(Vec3f(0,0,-1),2); Plane pfar(Vec3f(0,0,1),7); Plane pright(Vec3f(-0.7071,0,-0.7071),0); Plane pleft(Vec3f(0.7071,0,-0.7071),0); Plane ptop(Vec3f(0,-0.7071,-0.7071),0); Plane pbottom(Vec3f(0,0.7071,-0.7071),0); FrustumVolume frustum(pnear, pfar, pleft, pright, ptop, pbottom); //Frustum defined by a clipMatrix Matrix matrix; matrix.setValue(0.7071,0,0,0, 0,0.7071,0,0, 0,0,-1.27,-3.959, 0,0,-0.7071,0); FrustumVolume frustum1; frustum1.setPlanes(matrix); // Frustum defined by 8 points Pnt3f nlt(-2,2,-2); Pnt3f nlb(-2,-2,-2); Pnt3f nrt(2,2,-2); Pnt3f nrb(2,-2,-2); Pnt3f flt(-7,7,-7); Pnt3f flb(-7,-7,-7); Pnt3f frt(7,7,-7); Pnt3f frb(7,-7,-7); FrustumVolume frustum2; frustum2.setPlanes(nlt, nlb, nrt, nrb, flt, flb, frt, frb); //Tests std::cout << "Box/box outside test: " << std::flush; std::cout << (box.intersect(boxOut) ? "**BAD**" : "ok") << std::endl; std::cout << "Box/box inside test: " << std::flush; std::cout << (box.intersect(boxIn) ? "ok" : "**BAD**") << std::endl; std::cout << "Box/sphere outside test: " << std::flush; std::cout << (box.intersect(sphereOut) ? "**BAD**" : "ok") << std::endl; std::cout << "Box/sphere inside test: " << std::flush; std::cout << (box.intersect(sphereIn) ? "ok" : "**BAD**")<< std::endl; std::cout << "Sphere/sphere outside test: " << std::flush; std::cout << (sphere.intersect(sphereOut) ? "**BAD**" : "ok") << std::endl; std::cout << "Sphere/sphere inside test: " << std::flush; std::cout << (sphere.intersect(sphereIn) ? "ok" : "**BAD**") << std::endl; std::cout << "Box/cylinder outside test: " << std::flush; std::cout << (box.intersect(cylinderOut) ? "**BAD**" : "ok") << std::endl; std::cout << "Box/cylinder inside test: " << std::flush; std::cout << (box.intersect(cylinderIn) ? "ok" : "**BAD**") << std::endl; std::cout << "Sphere/cylinder outside test: " << std::flush; std::cout << (sphere.intersect(cylinderOut) ? "**BAD**" : "ok") << std::endl; std::cout << "Sphere/cylinder inside test: " << std::flush; std::cout << (sphere.intersect(cylinderIn) ? "ok" : " **BAD**") << std::endl; std::cout << "Cylinder/cylinder outside test: "<<std::flush; std::cout << (cylinder.intersect(cylinderOut) ? "**BAD**" : "ok")<<std::endl; std::cout << "Cylinder/cylinder inside test: "<<std::flush; std::cout << (cylinder.intersect(cylinderIn) ? "ok" : " **BAD** ")<<std::endl; std::cout << "Box/Frustum outside test : " << std::flush; std::cout << (boxOut.intersect(frustum) ? "**BAD**" : "ok") << std::endl; std::cout << "Box/Frustum inside test : " << std::flush; std::cout << (boxIn.intersect(frustum) ? "ok" : "**BAD**") << std::endl; std::cout << "Sphere/Frustum outside test : " << std::flush; std::cout << (sphereOut.intersect(frustum) ? "**BAD**" : "ok") << std::endl; std::cout << "Sphere/Frustum inside test : " << std::flush; std::cout << (sphereIn.intersect(frustum) ? "ok" : "**BAD**") << std::endl; std::cout << "Cylinder/Frustum outside test : " << std::flush; std::cout << (cylinderOut.intersect(frustum) ? "**BAD**" : "ok") << std::endl; std::cout << "Cylinder/Frustum inside test : " << std::flush; std::cout << (cylinderIn.intersect(frustum) ? "ok" : "**BAD**") << std::endl; std::cout << "Cylinder/Sphere outside test: " << std::flush; std::cout << (cylinderOut.intersect(sphere) ? "**BAD**" : "ok") << std::endl; //###VOLUME EXTENSION################################################ std::cout << "### volume extension test ###" << std::endl; Pnt3f min,max; //Box extension extend(box, boxIn); box.getBounds(min,max); std::cout<< "min of the box : " <<min<<std::endl; std::cout<< "max of the box : " <<max<<std::endl; extend(box,sphere); box.getBounds(min,max); std::cout<< "min of the box : " <<min<<std::endl; std::cout<< "max of the box : " <<max<<std::endl; extend(box,cylinder); box.getBounds(min,max); std::cout<< "min of the box : " <<min<<std::endl; std::cout<< "max of the box : " <<max<<std::endl; //Sphere extension extend(sphere, box); std::cout<<"Center of the sphere : " <<sphere.getCenter()<<std::endl; std::cout<<"Radius of the sphere : " <<sphere.getRadius()<<std::endl; extend(sphere, sphereOut); std::cout<<"Center of the sphere : " <<sphere.getCenter()<<std::endl; std::cout<<"Radius of the sphere : " <<sphere.getRadius()<<std::endl; extend(sphere, cylinder); std::cout<<"Center of the sphere : " <<sphere.getCenter()<<std::endl; std::cout<<"Radius of the sphere : " <<sphere.getRadius()<<std::endl; //Cylinder extension extend (cylinder, box); cylinder.getBounds(min,max); std::cout<< "min of the cylinder : " <<min<<std::endl; std::cout<< "max of the cylinder : " <<max<<std::endl; extend (cylinder, sphere); cylinder.getBounds(min,max); std::cout<< "min of the cylinder : " <<min<<std::endl; std::cout<< "max of the cylinder : " <<max<<std::endl; extend (cylinder, cylinder); cylinder.getBounds(min,max); std::cout<< "min of the cylinder : " <<min<<std::endl; std::cout<< "max of the cylinder : " <<max<<std::endl; return 0; }
OSG_BASE_DLLMAPPING void extend(CylinderVolume &srcVol, const BoxVolume &vol) { Pnt3f min, max, min1, max1, min2, max2, apos; Vec2f p; Vec3f adir; Real32 r; 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); p = Vec2f(max.x() - min.x(), max.y() - min.y()); r = (p.length()) * 0.5f; adir = Vec3f(0.f, 0.f, max.z() - min.z()); apos = Pnt3f(p.x(), p.y(), min.z()); srcVol.setValue(apos, adir, r); return; } } else if(vol.isEmpty()) { return; } srcVol.getBounds(min, max ); vol .getBounds(min1, max1); min2 = Pnt3f(osgMin(min.x(), min1.x()), osgMin(min.y(), min1.y()), osgMin(min.z(), min1.z())); max2 = Pnt3f(osgMax(max.x(), max1.x()), osgMax(max.y(), max1.y()), osgMax(max.z(), max1.z())); p = Vec2f(max2.x() - min2.x(), max2.y() - min2.y()); r = (p.length()) * 0.5f; adir = Vec3f(0.f, 0.f, max2.z() - min2.z()); apos = Pnt3f(p.x(), p.y(), min2.z()); srcVol.setValue(apos, adir, r); return; }
void selectedNodeChanged(void) { mgr->setHighlight(SelectedNode); //Update Details Panel if(SelectedNode == NULL) { NodeNameValueLabel->setText(""); NodeCoreTypeValueLabel->setText(""); NodeMinValueLabel->setText(""); NodeMaxValueLabel->setText(""); NodeCenterValueLabel->setText(""); NodeTriCountValueLabel->setText(""); NodeTravMaskValueLabel->setText(""); NodeOcclusionMaskValueLabel->setText(""); NodeActiveValueLabel->setText(""); } else { const Char8 *NodeName = getName(SelectedNode); if(NodeName == NULL) { NodeNameValueLabel->setText("Unnamed Node"); } else { NodeNameValueLabel->setText(NodeName); } NodeCoreTypeValueLabel->setText(SelectedNode->getCore()->getType().getCName()); BoxVolume DyVol; SelectedNode->getWorldVolume(DyVol); Pnt3f Min,Max,Center; DyVol.getBounds(Min,Max); DyVol.getCenter(Center); std::string TempText(""); TempText = boost::lexical_cast<std::string>(Min.x()) + ", " +boost::lexical_cast<std::string>(Min.x()) + ", " + boost::lexical_cast<std::string>(Min.x()); NodeMinValueLabel->setText(TempText); TempText = boost::lexical_cast<std::string>(Max.x()) + ", " +boost::lexical_cast<std::string>(Max.x()) + ", " + boost::lexical_cast<std::string>(Max.x()); NodeMaxValueLabel->setText(TempText); TempText = boost::lexical_cast<std::string>(Center.x()) + ", " +boost::lexical_cast<std::string>(Center.x()) + ", " + boost::lexical_cast<std::string>(Center.x()); NodeCenterValueLabel->setText(TempText); //GeometryPrimitivesCounter PrimCounter; //PrimCounter(SelectedNode); //NodeTriCountValueLabel->setText(boost::lexical_cast<std::string>(PrimCounter.getTriCount())); //NodeTravMaskValueLabel->setText(boost::lexical_cast<std::string>(SelectedNode->getTravMask())); //NodeOcclusionMaskValueLabel->setText(boost::lexical_cast<std::string>(SelectedNode->getOcclusionMask())); //NodeActiveValueLabel->setText(boost::lexical_cast<std::string>(SelectedNode->getActive())); } }