bool AttributeAttractRepelParticleAffector::affect(ParticleSystemRefPtr System, Int32 ParticleIndex, const Time& elps) { if(System != NULL) { Vec3f Displacement(System->getSecPosition(ParticleIndex) - System->getPosition(ParticleIndex) ); Real32 Distance(Displacement.squareLength()); if((Distance > getMinDistance()*getMinDistance()) && (Distance < getMaxDistance()*getMaxDistance())) { Distance = osgSqrt(Distance); Displacement.normalize(); Real32 t((getQuadratic() * (Distance*Distance) + getLinear() * Distance + getConstant())*elps); if(t > Distance) { t=Distance; } System->setPosition(System->getPosition(ParticleIndex) + (Displacement * t),ParticleIndex) ; } } return false; }
bool Line::intersect(const SphereVolume &sphere, Real &enter, Real &exit ) const { Vec3r v; Pnt3r center; sphere.getCenter(center); Real radius; Real h; Real b; Real d; Real t1; Real t2; radius = sphere.getRadius(); v = center - _pos; h = (v.dot(v))-(radius * radius); b = (v.dot(_dir)); if(h >= 0.f && b <= 0.f) return false; d = b * b - h; if(d < 0.f) return false; d = osgSqrt(d); t1 = b - d; // if (t1 > 1) // return false; t2 = b + d; if( t1 < TypeTraits<Real>::getDefaultEps() ) { if( t2 < TypeTraits<Real>::getDefaultEps() /*|| t2 > 1*/) { return false; } } enter = t1; exit = t2; return true; }
void ShaderShadowMapEngine::calcPointLightRange( const PointLight *pointL, Real32 lightThreshold, Real32 defaultNear, Real32 defaultFar, Real32 &outNear, Real32 &outFar ) { outNear = defaultNear; outFar = defaultFar; Real32 kQ = pointL->getQuadraticAttenuation(); Real32 kL = pointL->getLinearAttenuation (); Real32 kC = pointL->getConstantAttenuation (); if(osgAbs(kQ) > TypeTraits<Real32>::getDefaultEps()) { Real32 det = kL * kL - 4.f * kQ * (kC - 1.f / lightThreshold); if(det >= 0) { det = osgSqrt(det); Real32 r1 = - kL + det / (2.f * kQ); Real32 r2 = - kL - det / (2.f * kQ); if(r1 > 0.f && r2 > 0.f) { outFar = osgMin(r1, r2); } else if(r1 > 0.f) { outFar = r1; } else if(r2 > 0.f) { outFar = r2; } } } else if(osgAbs(kL) > TypeTraits<Real32>::getDefaultEps()) { Real32 r = (1.f / lightThreshold - kC) / kL; if(r > 0.f) { outFar = r; } } }
Vec3f CylinderDistribution3D::generate(void) const { Vec3f Result; switch(getSurfaceOrVolume()) { case SURFACE: { std::vector<Real32> Areas; //Min Cap Areas.push_back(0.5*osgAbs(getMaxTheta() - getMinTheta())*(getOuterRadius()*getOuterRadius() - getInnerRadius()*getInnerRadius())); //Max Cap Areas.push_back(Areas.back() + 0.5*osgAbs(getMaxTheta() - getMinTheta())*(getOuterRadius()*getOuterRadius() - getInnerRadius()*getInnerRadius())); //Inner Tube Areas.push_back(Areas.back() + getInnerRadius()*osgAbs(getMaxTheta() - getMinTheta()) * getHeight()); //Outer Tube Areas.push_back(Areas.back() + getOuterRadius()*osgAbs(getMaxTheta() - getMinTheta()) * getHeight()); bool HasTubeSides(osgAbs(getMaxTheta() - getMinTheta()) - 6.283185 < -0.000001); if(HasTubeSides) { //MinTheta Tube Side Areas.push_back(Areas.back() + (getOuterRadius() - getInnerRadius()) * getHeight()); //MaxTheta Tube Side Areas.push_back(Areas.back() + (getOuterRadius() - getInnerRadius()) * getHeight()); } Real32 PickEdge(RandomPoolManager::getRandomReal32(0.0,1.0)); if(PickEdge < Areas[0]/Areas.back()) { //Max Cap Real32 Temp(osgSqrt(RandomPoolManager::getRandomReal32(0.0,1.0))); Real32 Radius(getInnerRadius() + Temp*(getOuterRadius() - getInnerRadius())); Real32 Theta( RandomPoolManager::getRandomReal32(getMinTheta(),getMaxTheta()) ); Result = getCenter().subZero() + (Radius*osgSin(Theta))*getTangent() + (Radius*osgCos(Theta))*getBinormal() + (getHeight()/static_cast<Real32>(2.0))*getNormal(); } else if(PickEdge < Areas[1]/Areas.back()) { //Min Cap Real32 Temp(osgSqrt(RandomPoolManager::getRandomReal32(0.0,1.0))); Real32 Radius(getInnerRadius() + Temp*(getOuterRadius() - getInnerRadius())); Real32 Theta( RandomPoolManager::getRandomReal32(getMinTheta(),getMaxTheta()) ); Result = getCenter().subZero() + (Radius*osgSin(Theta))*getTangent() + (Radius*osgCos(Theta))*getBinormal() + (-getHeight()/static_cast<Real32>(2.0))*getNormal(); } else if(PickEdge < Areas[2]/Areas.back()) { //Inner Tube Real32 Theta( RandomPoolManager::getRandomReal32(getMinTheta(),getMaxTheta()) ); Real32 Height(RandomPoolManager::getRandomReal32(-getHeight()/2.0,getHeight()/2.0)); Result = getCenter().subZero() + getInnerRadius()*osgSin(Theta)*getTangent() + getInnerRadius()*osgCos(Theta)*getBinormal() + Height*getNormal(); } else if(PickEdge < Areas[3]/Areas.back()) { //Outer Tube Real32 Theta( RandomPoolManager::getRandomReal32(getMinTheta(),getMaxTheta()) ); Real32 Height(RandomPoolManager::getRandomReal32(-getHeight()/2.0,getHeight()/2.0)); Result = getCenter().subZero() + getOuterRadius()*osgSin(Theta)*getTangent() + getOuterRadius()*osgCos(Theta)*getBinormal() + Height*getNormal(); } else if(HasTubeSides && PickEdge < Areas[4]/Areas.back()) { //MinTheta Tube Side Real32 Temp(osgSqrt(RandomPoolManager::getRandomReal32(0.0,1.0))); Real32 Radius(getInnerRadius() + Temp*(getOuterRadius() - getInnerRadius())); Real32 Height(RandomPoolManager::getRandomReal32(-getHeight()/2.0,getHeight()/2.0)); Result = getCenter().subZero() + (Radius*osgSin(getMinTheta()))*getTangent() + (Radius*osgCos(getMinTheta()))*getBinormal() + Height*getNormal(); } else if(HasTubeSides && PickEdge < Areas[5]/Areas.back()) { //MaxTheta Tube Side Real32 Temp(osgSqrt(RandomPoolManager::getRandomReal32(0.0,1.0))); Real32 Radius(getInnerRadius() + Temp*(getOuterRadius() - getInnerRadius())); Real32 Height(RandomPoolManager::getRandomReal32(-getHeight()/2.0,getHeight()/2.0)); Result = getCenter().subZero() + (Radius*osgSin(getMaxTheta()))*getTangent() + (Radius*osgCos(getMaxTheta()))*getBinormal() + Height*getNormal(); } else { assert(false && "Should never reach this point"); } break; } case VOLUME: default: { //To get a uniform distribution across the disc get a uniformly distributed allong 0.0 - 1.0 //Then Take the square root of that. This gives a square root distribution from 0.0 - 1.0 //This square root distribution is used for the random radius because the area of a disc is //dependant on the square of the radius, i.e it is a quadratic function Real32 Temp(osgSqrt(RandomPoolManager::getRandomReal32(0.0,1.0))); Real32 Radius(getInnerRadius() + Temp*(getOuterRadius() - getInnerRadius())); Real32 Height(RandomPoolManager::getRandomReal32(-getHeight()/2.0,getHeight()/2.0)); Real32 Theta( RandomPoolManager::getRandomReal32(getMinTheta(),getMaxTheta()) ); Result = getCenter().subZero() + (Radius*osgSin(Theta))*getTangent() + (Radius*osgCos(Theta))*getBinormal() + Height*getNormal(); break; } } return Result; }
/*! Calculates the trapezoidal transformation matrix \a matNT that transforms post projection light space so that shadow map resolution in the "foreground" is maximized. The major steps are: - compute the intersection of eyeFrust and lightFrust - construct a trapezoid that contains the intersection - determine the transformation that maps this trapezoid to the (-1, 1) square Returns \c true if the transform was computed, \c false otherwise (e.g. if the intersection of eyeFrust and lightFrust is empty). For details see "T. Martin, T.-S. Tan: Anti-aliasing and Continuity with Trapezoidal Shadow Maps" */ bool TrapezoidalShadowMapEngine::calcTrapezoidalTransform( Matrixr &matNT, const Matrixr &matEyeToWorld, const Matrixr &matLightFull, const FrustumVolume &eyeFrust, const FrustumVolume &lightFrust ) { // obtain post proj. light space eye position Pnt3r eyePos; matEyeToWorld.mult (eyePos, eyePos); matLightFull .multFull(eyePos, eyePos); // intersect eye and light frusta, get vertices and center of intersection std::vector<Pnt3r> intVerts; Pnt3r intCenter; intersectFrusta(eyeFrust, lightFrust, intVerts, intCenter); if(intVerts.empty() == true) return false; // xform intCenter and intVerts to post proj. light space matLightFull.multFull(intCenter, intCenter); std::vector<Pnt3r>::iterator ivIt = intVerts.begin(); std::vector<Pnt3r>::iterator ivEnd = intVerts.end (); for(; ivIt != ivEnd; ++ivIt) matLightFull.multFull(*ivIt, *ivIt); Pnt2r eyePos2D (eyePos [0], eyePos [1]); Pnt2r intCenter2D(intCenter[0], intCenter[1]); // center line, normal, direction and distance from origin Vec2r clDir (intCenter2D - eyePos2D); clDir.normalize(); Vec2r clNorm(-clDir[1], clDir[0]); // distance of the center line from the origin Real clDist = clNorm.dot(eyePos2D.subZero()); // compute top and base lines: // - project intVerts onto the center line. // - top line is perpendicular to center line and goes through the // projected point closest to eyePos // - base line is perpendicular to center line and goes through the // projected point farthest from eyePos Pnt2r tlBase; Pnt2r blBase; Real topDist = TypeTraits<Real>::getMax(); Real baseDist = TypeTraits<Real>::getMin(); std::vector<Pnt3r>::const_iterator ivCIt = intVerts.begin(); std::vector<Pnt3r>::const_iterator ivCEnd = intVerts.end (); for(; ivCIt != ivCEnd; ++ivCIt) { Pnt2r ivPnt((*ivCIt)[0], (*ivCIt)[1]); ivPnt = ivPnt - (clNorm.dot(ivPnt) - clDist) * clNorm; Real dist = (ivPnt - eyePos2D).squareLength(); dist *= osgSgn(clDir.dot(ivPnt - eyePos2D)); if(dist < topDist) { topDist = dist; tlBase = ivPnt; } if(dist > baseDist) { baseDist = dist; blBase = ivPnt; } } topDist = osgSgn(topDist ) * osgSqrt(osgAbs(topDist )); baseDist = osgSgn(baseDist) * osgSqrt(osgAbs(baseDist)); // compute side lines: // - choose focusPnt (everything closer to the near plane is mapped to // 80% of the shadow map) - here we just take the point at 0.7 between // tlBase and blBase // - find a point (trapTip, q in the paper) on center line such that // focusPnt is mapped the 80% line in the shadow map // - choose lines through q that touch the convex hull of intVerts ivCIt = intVerts.begin(); ivCEnd = intVerts.end (); // Real centerDist = (intCenter2D - eyePos2D).length(); Real lambda = baseDist - topDist; Real delta = 0.5f * lambda; Real xi = -0.6f; Real eta = ((lambda * delta) + (lambda * delta * xi)) / (lambda - 2.f * delta - lambda * xi ); Pnt2r trapTip = tlBase - (eta * clDir); Pnt2r focusPnt = tlBase + (delta * clDir); // on both sides of the center line, find the point in intVerts that has // the smallest |cosine| (largest angle) between clDir and the vector // from trapTip to intVerts[i] Pnt2r posPnt; Real posCos = 1.f; Pnt2r negPnt; Real negCos = 1.f; for(UInt32 i = 0; ivCIt != ivCEnd; ++ivCIt, ++i) { Pnt2r ivPnt((*ivCIt)[0], (*ivCIt)[1]); Vec2r v = ivPnt - trapTip; v.normalize(); Real currCos = osgAbs(clDir.dot(v)); if(clNorm.dot(v) >= 0.f) { if(currCos <= posCos) { posPnt = ivPnt; posCos = currCos; } } else { if(currCos <= negCos) { negPnt = ivPnt; negCos = currCos; } } } // compute corners of trapezoid: Pnt2r trapVerts [4]; Pnt2r extraVerts[2]; Real posTan = osgTan(osgACos(posCos)); Real negTan = osgTan(osgACos(negCos)); trapVerts[0] = blBase - ((eta + lambda) * negTan * clNorm); trapVerts[1] = blBase + ((eta + lambda) * posTan * clNorm); trapVerts[2] = tlBase + ( eta * posTan * clNorm); trapVerts[3] = tlBase - ( eta * negTan * clNorm); extraVerts[0] = focusPnt + ((eta + delta) * posTan * clNorm); extraVerts[1] = focusPnt - ((eta + delta) * negTan * clNorm); // == xform trapezoid to unit square == // M1 = R * T1 -- translate center of top line to origin and rotate Vec2r u = 0.5f * (trapVerts[2].subZero() + trapVerts[3].subZero()); Vec2r v = trapVerts[3] - trapVerts[2]; v.normalize(); matNT.setValue( v[0], v[1], 0.f, -(u[0] * v[0] + u[1] * v[1]), -v[1], v[0], 0.f, (u[0] * v[1] - u[1] * v[0]), 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f); // M2 = T2 * M1 -- translate tip to origin matNT[3][0] = - (matNT[0][0] * trapTip[0] + matNT[1][0] * trapTip[1]); matNT[3][1] = - (matNT[0][1] * trapTip[0] + matNT[1][1] * trapTip[1]); // M3 = H * M2 -- shear to make it symmetric wrt to the y axis // v = M2 * u v[0] = matNT[0][0] * u[0] + matNT[1][0] * u[1] + matNT[3][0]; v[1] = matNT[0][1] * u[0] + matNT[1][1] * u[1] + matNT[3][1]; Real a = - v[0] / v[1]; // matNT[*][0] : = mat[*][0] + a * mat[*][1] matNT[0][0] += a * matNT[0][1]; matNT[1][0] += a * matNT[1][1]; matNT[2][0] += a * matNT[2][1]; matNT[3][0] += a * matNT[3][1]; // M4 = S1 * M3 -- scale to make sidelines orthogonal and // top line is at y == 1 // v = 1 / (M3 * t2) v[0] = 1.f / (matNT[0][0] * trapVerts[2][0] + matNT[1][0] * trapVerts[2][1] + matNT[3][0]); v[1] = 1.f / (matNT[0][1] * trapVerts[2][0] + matNT[1][1] * trapVerts[2][1] + matNT[3][1]); matNT[0][0] *= v[0]; matNT[0][1] *= v[1]; matNT[1][0] *= v[0]; matNT[1][1] *= v[1]; matNT[2][0] *= v[0]; matNT[2][1] *= v[1]; matNT[3][0] *= v[0]; matNT[3][1] *= v[1]; // M5 = N * M4 -- turn trapezoid into rectangle matNT[0][3] = matNT[0][1]; matNT[1][3] = matNT[1][1]; matNT[2][3] = matNT[2][1]; matNT[3][3] = matNT[3][1]; matNT[3][1] += 1.f; // M6 = T3 * M5 -- translate center to origin // u = "M5 * t0" - only y and w coordinates // v = "M5 * t2" - only y and w coordinates u[0] = matNT[0][1] * trapVerts[0][0] + matNT[1][1] * trapVerts[0][1] + matNT[3][1]; u[1] = matNT[0][3] * trapVerts[0][0] + matNT[1][3] * trapVerts[0][1] + matNT[3][3]; v[0] = matNT[0][1] * trapVerts[2][0] + matNT[1][1] * trapVerts[2][1] + matNT[3][1]; v[1] = matNT[0][3] * trapVerts[2][0] + matNT[1][3] * trapVerts[2][1] + matNT[3][3]; a = - 0.5f * (u[0] / u[1] + v[0] / v[1]); matNT[0][1] += matNT[0][3] * a; matNT[1][1] += matNT[1][3] * a; matNT[2][1] += matNT[2][3] * a; matNT[3][1] += matNT[3][3] * a; // M7 = S2 * M6 -- scale to fill -1/+1 square // u = "M6 * t0" - only y and w coordinates u[0] = matNT[0][1] * trapVerts[0][0] + matNT[1][1] * trapVerts[0][1] + matNT[3][1]; u[1] = matNT[0][3] * trapVerts[0][0] + matNT[1][3] * trapVerts[0][1] + matNT[3][3]; a = -u[1] / u[0]; matNT[0][1] *= a; matNT[1][1] *= a; matNT[2][1] *= a; matNT[3][1] *= a; return true; }
void FrustumVolume::setPlanes(const Matrix &objectClipMat) { Vec4f planeEquation[6]; Real32 vectorLength; Vec3f normal; planeEquation[0][0] = objectClipMat[0][3] - objectClipMat[0][0]; planeEquation[0][1] = objectClipMat[1][3] - objectClipMat[1][0]; planeEquation[0][2] = objectClipMat[2][3] - objectClipMat[2][0]; planeEquation[0][3] = objectClipMat[3][3] - objectClipMat[3][0]; planeEquation[1][0] = objectClipMat[0][3] + objectClipMat[0][0]; planeEquation[1][1] = objectClipMat[1][3] + objectClipMat[1][0]; planeEquation[1][2] = objectClipMat[2][3] + objectClipMat[2][0]; planeEquation[1][3] = objectClipMat[3][3] + objectClipMat[3][0]; planeEquation[2][0] = objectClipMat[0][3] + objectClipMat[0][1]; planeEquation[2][1] = objectClipMat[1][3] + objectClipMat[1][1]; planeEquation[2][2] = objectClipMat[2][3] + objectClipMat[2][1]; planeEquation[2][3] = objectClipMat[3][3] + objectClipMat[3][1]; planeEquation[3][0] = objectClipMat[0][3] - objectClipMat[0][1]; planeEquation[3][1] = objectClipMat[1][3] - objectClipMat[1][1]; planeEquation[3][2] = objectClipMat[2][3] - objectClipMat[2][1]; planeEquation[3][3] = objectClipMat[3][3] - objectClipMat[3][1]; planeEquation[4][0] = objectClipMat[0][3] + objectClipMat[0][2]; planeEquation[4][1] = objectClipMat[1][3] + objectClipMat[1][2]; planeEquation[4][2] = objectClipMat[2][3] + objectClipMat[2][2]; planeEquation[4][3] = objectClipMat[3][3] + objectClipMat[3][2]; planeEquation[5][0] = objectClipMat[0][3] - objectClipMat[0][2]; planeEquation[5][1] = objectClipMat[1][3] - objectClipMat[1][2]; planeEquation[5][2] = objectClipMat[2][3] - objectClipMat[2][2]; planeEquation[5][3] = objectClipMat[3][3] - objectClipMat[3][2]; for(Int32 i = 0; i < 6; i++) { vectorLength = osgSqrt(planeEquation[i][0] * planeEquation[i][0] + planeEquation[i][1] * planeEquation[i][1] + planeEquation[i][2] * planeEquation[i][2]); planeEquation[i][0] /= vectorLength; planeEquation[i][1] /= vectorLength; planeEquation[i][2] /= vectorLength; planeEquation[i][3] /= -vectorLength; } // right _planeVec[3].set(planeEquation[0]); // left _planeVec[2].set(planeEquation[1]); // bottom _planeVec[5].set(planeEquation[2]); // top _planeVec[4].set(planeEquation[3]); // near _planeVec[0].set(planeEquation[4]); // far _planeVec[1].set(planeEquation[5]); }
void BbqGeoRefdTerrainRenderer<HeightType, HeightDeltaType, TextureType >::render( BbqTerrNode *rootNode, const BbqRenderOptions &options ) { _oStatistics.nodeCount = 0; _oStatistics.triangleCount = 0; traversalStack_.push_back(rootNode); // activate the shader: // glUseProgramObjectARB( terrainShader_.getProgramHandle() ); // terrainShader_.activate(options.pDrawEnv); // fprintf(stderr, "Frame start\n"); while(!traversalStack_.empty()) { BbqTerrNode *node = traversalStack_.back(); assert(node); traversalStack_.pop_back(); #ifdef GV_CHECK // cull this node->. if( options.enableFrustumCulling && !isIntersecting( options.frustum, node->boundingBox ) ) { // not visible at all _oStatistics.culledNodeCount++; continue; } #endif const Real32 detailFactor = options.screenSpaceError; //todo: i need to use the distance to Pnt3f bboxCenter; Vec3f dist; node->boundingBox.getCenter(bboxCenter); /* fprintf(stderr, "%d %f %f %f\n", node->id, bboxCenter[0], bboxCenter[1], bboxCenter[2]); */ dist = options.viewerpos - bboxCenter; const float distance = osgMax(dist.length(), 0.001f); // const float distance = osgMax( // getMagnitude( options.frustum.getPosition() - // node->boundingBox.getCenter() ), 0.001f ); //// todo: instead of the size of the node, use the maximum error bound Vec3f bboxSize; node->boundingBox.getSize(bboxSize); // const float nodeSize = node->boundingBox.getSize().x; const float nodeSize = bboxSize.x(); // const float fovY = options.frustum.getFovY(); const float fovY = options.fovy; const float screenResolution = float( options.screenSize.y() ) / fovY; #if 0 //Unused const float nodeError = screenResolution * ( ( nodeSize / float( _oDatabaseInfo.heightTileSize ) ) / distance ); const float objectSpaceHeightError = float( node->maxHeightError ) / 32767.0f * _oDatabaseInfo.heightScale + _oDatabaseInfo.heightOffset; // 65535.0f * _oDatabaseInfo.heightScale + _oDatabaseInfo.heightOffset; const float screenSpaceHeightError = ( objectSpaceHeightError / distance ) * screenResolution; const float screenFactor = float( options.screenSize.y() ) / ( 2.0f * tanf( fovY / 2.0f ) ); const float screenSpaceHeightError2 = ( objectSpaceHeightError / distance ) * screenFactor; const float switchDistance2 = ( objectSpaceHeightError / detailFactor ) * screenFactor; #endif // todo: geomorphing geht noch nicht richtig... Vec3f disp = options.viewerpos - bboxCenter; // options.frustum.getPosition() - node->boundingBox.getCenter(); // Vec3f extent = node->boundingBox.getSize(); Vec3f extent; node->boundingBox.getSize(extent); disp[0] = osgMax( 0.0f, fabsf( disp.x() ) - extent.x() ); disp[1] = osgMax( 0.0f, fabsf( disp.y() ) - extent.y() ); disp[2] = osgMax( 0.0f, fabsf( disp.z() ) - extent.z() ); // disp.y = 0; // for debugging // float d = 0; // d = osgSqrt( dot( disp, disp ) ); // d = osgSqrt( disp.dot(disp) ); // float // const float tan_half_FOV = tanf(0.5f * horizontal_FOV_degrees // * (float) M_PI / 180.0f); // // const float K = screen_width_pixels / tan_half_FOV; // // distance_LODmax is the distance below which we need to be // // at the maximum LOD. It's used in compute_lod(), which is // // called by the chunks during update(). // m_distance_LODmax = ; // return fmax(1, d / (objectSpaceHeightError / detailFactor) * K); //} //float switchDistance2 = ( objectSpaceHeightError / detailFactor ) * //screenFactor; //float switchDistance = ( objectSpaceHeightError / detailFactor ) * //screenFactor; float switchDistance = ( nodeSize / float( _oDatabaseInfo.heightTileSize ) ) / detailFactor * screenResolution; float geomorphStartDistance = switchDistance + 145.0f; //const bool hasEnoughDetail = nodeError < detailFactor; /* fprintf(stderr, "%f | %f\n", distance, geomorphStartDistance); */ if( node->isLeafNode() || distance > geomorphStartDistance ) { // render the node: #ifndef GV_TEST Inherited::setGeoMorphingFactor( node ); #else _oTerrainShader.setUniform( "geoMorphFactor", options.geoMorphFactor ); #endif renderNodeVbo( node, options.showSkirts, options ); if( options.showBoundingBoxes ) { glColor3f( 0, 0, 1 ); this->renderBoundingBox( node->boundingBox, options ); } if( options.showSwitchDistance ) { // Pnt3f bboxCenter; node->boundingBox.getCenter(bboxCenter); glColor3f( 0, 1, 0 ); Inherited::renderSphere(bboxCenter , switchDistance, options ); } } else { // compute the geomorphing factor: //const float innerSwitchDistance = switchDistance - //switchDistance / 4.0f; node->geoMorphingFactor = clamp( 1.0f - ( switchDistance - distance ) / ( geomorphStartDistance - switchDistance ), 0.0f, 1.0f ); //node->geoMorphingFactor = 1.0f; // push the child nodes: // todo: push the nearest child last.. (to get a rough front to // back rendering order) static int order[ 4 ] = { 0, 1, 2, 3 }; //static float dist[ 4 ]; //if( options.sortChildren ) //{ // for( int i = 0; i < 4; ++i ) // { // dist[ i ] = getMagnitude( node->children[ i //]->boundingBox.getCenter() - options.frustum.getPosition() ); // for( int j = 0; j < i; ++j ) // { // if( dist[ i ] < // } // } //} traversalStack_.push_back( node->children[ order[ 0 ] ] ); traversalStack_.push_back( node->children[ order[ 1 ] ] ); traversalStack_.push_back( node->children[ order[ 2 ] ] ); traversalStack_.push_back( node->children[ order[ 3 ] ] ); } } glColor3f(1.f, 0.f, 0.f); glBegin(GL_QUADS); { glVertex3f(rootNode->boundingBox.getMin().x(), 0.f, rootNode->boundingBox.getMin().z()); glVertex3f(rootNode->boundingBox.getMax().x(), 0.f, rootNode->boundingBox.getMin().z()); glVertex3f(rootNode->boundingBox.getMax().x(), 0.f, rootNode->boundingBox.getMax().z()); glVertex3f(rootNode->boundingBox.getMin().x(), 0.f, rootNode->boundingBox.getMax().z()); } glEnd(); static bool dumpBox = false; if(dumpBox == false) { fprintf(stderr, "%f %f | %f %f\n", rootNode->boundingBox.getMin().x(), rootNode->boundingBox.getMin().z(), rootNode->boundingBox.getMax().x(), rootNode->boundingBox.getMax().z()); dumpBox = true; } // glUseProgramObjectARB( 0 ); // _oTerrainShader.deactivate(options.pDrawEnv); }
bool Line::intersect(const CylinderVolume &cyl, Real &enter, Real &exit ) const { Real radius = cyl.getRadius(); Vec3r adir; Vec3r o_adir; Pnt3r apos; cyl.getAxis(apos, adir); o_adir = adir; adir.normalize(); bool isect; Real ln; Real dl; Vec3r RC; Vec3r n; Vec3r D; RC = _pos - apos; n = _dir.cross (adir); ln = n .length( ); if(ln == 0.f) // IntersectionLine is parallel to CylinderAxis { D = RC - (RC.dot(adir)) * adir; dl = D.length(); if(dl <= radius) // line lies in cylinder { enter = 0.f; exit = Inf; } else { return false; } } else { n.normalize(); dl = osgAbs(RC.dot(n)); //shortest distance isect = (dl <= radius); if(isect) { // if ray hits cylinder Real t; Real s; Vec3r O; O = RC.cross(adir); t = - (O.dot(n)) / ln; O = n.cross(adir); O.normalize(); s = osgAbs ( (osgSqrt ((radius * radius) - (dl * dl))) / (_dir.dot(O))); exit = t + s; if(exit < 0.f) return false; enter = t - s; if(enter < 0.f) enter = 0.f; } else { return false; } } Real t; Plane bottom(-adir, apos); if(bottom.intersect(*this, t)) { if(bottom.isInHalfSpace(_pos)) { if(t > enter) enter = t; } else { if(t < exit) exit = t; } } else { if(bottom.isInHalfSpace(_pos)) return false; } Plane top(adir, apos + o_adir); if(top.intersect(*this, t)) { if(top.isInHalfSpace(_pos)) { if(t > enter) enter = t; } else { if(t < exit) exit = t; } } else { if(top.isInHalfSpace(_pos)) return false; } return (enter < exit); }