/** * @implementation * Adapted from: * <cite>'Fast, Minimum Storage Ray-Triangle Intersection'; * Moller, Trumbore; * Journal Of Graphics Tools, v2n1p21; 1997. * http://www.acm.org/jgt/papers/MollerTrumbore97/</cite> */ bool TriangleIntersection ( const Triangle* pT, const Vector3f* pRayOrigin, const Vector3f* pRayDirection, real64* pHitDistance_o ) { /* make vectors for two edges sharing vert0 */ const Vector3f edge1 = Vector3fSub( &pT->aVertexs[1], &pT->aVertexs[0] ); const Vector3f edge2 = Vector3fSub( &pT->aVertexs[2], &pT->aVertexs[0] ); /* begin calculating determinant - also used to calculate U parameter */ const Vector3f pvec = Vector3fCross( pRayDirection, &edge2 ); /* if determinant is near zero, ray lies in plane of triangle */ const real64 det = Vector3fDot( &edge1, &pvec ); bool isHit = false; if( (det <= -EPSILON) | (det >= EPSILON) ) { const real64 inv_det = 1.0 / det; /* calculate distance from vertex 0 to ray origin */ const Vector3f tvec = Vector3fSub( pRayOrigin, &pT->aVertexs[0] ); /* calculate U parameter and test bounds */ const real64 u = Vector3fDot( &tvec, &pvec ) * inv_det; if( (u >= 0.0) & (u <= 1.0) ) { /* prepare to test V parameter */ const Vector3f qvec = Vector3fCross( &tvec, &edge1 ); /* calculate V parameter and test bounds */ const real64 v = Vector3fDot( pRayDirection, &qvec ) * inv_det; if( (v >= 0.0) & (u + v <= 1.0) ) { /* calculate t, ray intersects triangle */ *pHitDistance_o = Vector3fDot( &edge2, &qvec ) * inv_det; /* only allow intersections in the forward ray direction */ isHit = (*pHitDistance_o >= 0.0); } } } return isHit; }
//Mouse drag, calculate rotation void ArcBall_t::drag(const Point2fT* NewPt, Quat4fT* NewRot) { //Map the point to the sphere this->_mapToSphere(NewPt, &this->EnVec); //Return the quaternion equivalent to the rotation if (NewRot) { Vector3fT Perp; //Compute the vector perpendicular to the begin and end vectors Vector3fCross(&Perp, &this->StVec, &this->EnVec); //Compute the length of the perpendicular vector if (Vector3fLength(&Perp) > Epsilon) //if its non-zero { //We're ok, so return the perpendicular vector as the transform after all NewRot->s.X = Perp.s.X; NewRot->s.Y = Perp.s.Y; NewRot->s.Z = Perp.s.Z; //In the quaternion values, w is cosine (theta / 2), where theta is rotation angle NewRot->s.W= Vector3fDot(&this->StVec, &this->EnVec); } else //if its zero { //The begin and end vectors coincide, so return an identity transform NewRot->s.X = NewRot->s.Y = NewRot->s.Z = NewRot->s.W = 0.0f; } } }
//Mouse drag, calculate rotation inline void ArcBallDrag(ArcBall_t *a, double x, double y, Quat4fT* NewRot) { //Map the point to the sphere ArcBallMapToSphere(a, x, y, &(a->EnVec)); //Return the quaternion equivalent to the rotation if (NewRot) { Vector3fT Perp; //Compute the vector perpendicular to the begin and end vectors Vector3fCross(&Perp, &(a->StVec), &(a->EnVec)); //Compute the length of the perpendicular vector if (Vector3fLength(&Perp) > ArcBallEpsilon) { //if its non-zero //We're ok, so return the perpendicular vector as the transform after all NewRot->s.X = Perp.s.X; NewRot->s.Y = Perp.s.Y; NewRot->s.Z = Perp.s.Z; //In the quaternion values, w is cosine (theta / 2), where theta is rotation angle NewRot->s.W= Vector3fDot(&(a->StVec), &(a->EnVec)); } else { //if its zero //The begin and end vectors coincide, so return an identity transform NewRot->s.X = 0.0f; NewRot->s.Y = 0.0f; NewRot->s.Z = 0.0f; NewRot->s.W = 0.0f; } } }
real64 TriangleArea ( const Triangle* pT ) { /* half area of parallelogram (area = magnitude of cross of two edges) */ const Vector3f normalV = TriangleNormalV( pT ); return sqrt( Vector3fDot( &normalV, &normalV ) ) * 0.5; }
static real64 ImageCalculateToneMapping ( const Image* pI, const int32u displayLumMax ) { /* calculate estimate of world-adaptation luminance as log mean luminance of scene */ real64 adaptLuminance = 1e-4; { real64 sumOfLogs = 0.0; int32 i; for( i = (pI->width * pI->height); i-- > 0; ) { const real64 Y = Vector3fDot( &pI->aPixels[i], &RGB_LUMINANCE ); /* clamp luminance to a perceptual minimum */ sumOfLogs += log10( Y > 1e-4 ? Y : 1e-4 ); } adaptLuminance = pow( 10.0, sumOfLogs / (real64)(pI->width * pI->height) ); } /* make scale-factor from: ratio of minimum visible differences in luminance, in display-adapted and world-adapted perception (discluding the constant that cancelled), divided by display max to yield a [0,1] range */ { const real64 displayLuminanceMax = displayLumMax ? (real64)displayLumMax : DISPLAY_LUMINANCE_MAX; const real64 a = 1.219 + pow( displayLuminanceMax * 0.25, 0.4 ); const real64 b = 1.219 + pow( adaptLuminance, 0.4 ); return pow( a / b, 2.5 ) / DISPLAY_LUMINANCE_MAX; } }