SolidAngle SolidAngle::fromCenterRadius(const Vector3<float>& to_center, float radius) { float to_center_len = to_center.length(); if (to_center_len <= radius) return SolidAngle(MaxVal); float sin_alpha = radius / to_center_len; float cos_alpha = sqrtf(1 - sin_alpha*sin_alpha); return SolidAngle( 2.0f * Pi * (1.0f - cos_alpha) ); }
f32 Rectangle::IntegrateStructuredSampling( const vec3f & integrationPos, const vec3f & integrationNrm ) const { // Solving E(n) = Int_lightArea [ Lin <n.l> dl ] == lightArea * Lin * Average[<n.l>] // With Average[<n.l>] approximated with the average of the 4 corners and center of the rect // unit space solid angle (== unit space area) f32 solidAngle = SolidAngle( integrationPos ); // unit space vectors to the 5 sample points vec3f q0 = Normalize( p0 - integrationPos ); vec3f q1 = Normalize( p1 - integrationPos ); vec3f q2 = Normalize( p2 - integrationPos ); vec3f q3 = Normalize( p3 - integrationPos ); vec3f q4 = Normalize( position - integrationPos ); // area * Average[<n.l>] (Lin is 1.0) return solidAngle * 0.2f * ( std::max( 0.f, Dot( q0, integrationNrm ) ) + std::max( 0.f, Dot( q1, integrationNrm ) ) + std::max( 0.f, Dot( q2, integrationNrm ) ) + std::max( 0.f, Dot( q3, integrationNrm ) ) + std::max( 0.f, Dot( q4, integrationNrm ) ) ); }
/*-------------------------------------------------------------------------* * Coord * * * * Compute the two coordinates (x1,x2) corresponding to a point in the * * spherical triangle. This is the inverse of "Chart". * * * *-------------------------------------------------------------------------*/ Vec2 SphericalTriangle::Coord( const Vec3 &P1 ) const { Vec3 P = Unit( P1 ); // Compute the new C vertex, which lies on the arc defined by B-P // and the arc defined by A-C. Vec3 C_new = Unit( ( B() ^ P ) ^ ( C() ^ A() ) ); // Adjust the sign of C_new. Make sure it's on the arc between A and C. if( C_new * ( A() + C() ) < 0.0 ) C_new = -C_new; // Compute x1, the area of the sub-triangle over the original area. float cos_beta = CosDihedralAngle( A(), B(), C_new ); float cos_gamma = CosDihedralAngle( A(), C_new , B() ); float sub_area = Alpha() + acos( cos_beta ) + acos( cos_gamma ) - Pi; float x1 = sub_area / SolidAngle(); // Now compute the second coordinate using the new C vertex. float z = P * B(); float x2 = ( 1.0 - z ) / ( 1.0 - C_new * B() ); if( x1 < 0.0 ) x1 = 0.0; if( x1 > 1.0 ) x1 = 1.0; if( x2 < 0.0 ) x2 = 0.0; if( x2 > 1.0 ) x2 = 1.0; return Vec2( x1, x2 ); }
bool decodeSolidAngle(v8::Handle<v8::Value> toDecode, SolidAngle& toDecodeTo, String& errMsg) { if (!NumericValidate(toDecode)) { errMsg += " Error decoding solid angle. Passed in parameter was not of numeric type"; return false; } toDecodeTo = SolidAngle(NumericExtract(toDecode)); return true; }
void ObjectFactory::generateRandomObjects(const BoundingBox3f& region, const Duration& duration, double forceRadius, int forceNumRandomObjects) { Time start(Time::null()); Time end = start + duration; Vector3f region_extents = region.extents(); uint32 nobjects = GetOptionValue<uint32>(OBJECT_NUM_RANDOM); if (forceNumRandomObjects) nobjects=forceNumRandomObjects; if (nobjects == 0) return; bool simple = GetOptionValue<bool>(OBJECT_SIMPLE); bool only_2d = GetOptionValue<bool>(OBJECT_2D); std::string motion_path_type = GetOptionValue<String>(OBJECT_STATIC); float driftX = GetOptionValue<float>(OBJECT_DRIFT_X); float driftY = GetOptionValue<float>(OBJECT_DRIFT_Y); float driftZ = GetOptionValue<float>(OBJECT_DRIFT_Z); float percent_queriers = GetOptionValue<float>(OBJECT_QUERY_FRAC); Vector3f driftVecDir(driftX,driftY,driftZ); for(uint32 i = 0; i < nobjects; i++) { UUID id = randomUUID(); ObjectInputs* inputs = new ObjectInputs; Vector3f startpos = region.min() + Vector3f(randFloat()*region_extents.x, randFloat()*region_extents.y, (only_2d ? 0.5 : randFloat())*region_extents.z); double radval = forceRadius; if (!radval) radval=10; float bounds_radius = (simple ? radval : (randFloat()*2*radval)); //SILOG(oh,error,"Creating "<<id.toString()<<" radius "<<bounds_radius); inputs->localID = mLocalIDSource++; if (motion_path_type == "static")//static inputs->motion = new StaticMotionPath(start, startpos); else if (motion_path_type == "drift") //drift { // inputs->motion = new OSegTestMotionPath(start, end, startpos, 3, Duration::milliseconds((int64)1000), region, zfactor); // FIXME inputs->motion = new OSegTestMotionPath(start, end, startpos, 3, Duration::milliseconds((int64)1000), region, 0.5, driftVecDir); // FIXME } else //random inputs->motion = new RandomMotionPath(start, end, startpos, 3, Duration::milliseconds((int64)1000), region, (only_2d ? 0.0 : 1.0)); // FIXME inputs->bounds = BoundingSphere3f( Vector3f(0, 0, 0), bounds_radius ); inputs->registerQuery = (randFloat() <= percent_queriers); inputs->queryAngle = SolidAngle(SolidAngle::Max / 900.f); // FIXME how to set this? variability by objects? inputs->connectAt = Duration::seconds(0.f); inputs->startTimer = Network::IOTimer::create(mContext->ioService); mObjectIDs.insert(id); mInputs[id] = inputs; } }
f32 Polygon::AxialMomentArvo( const vec3f & w, int order ) { f32 a = -BoundaryIntegralArvo( w, w, 0, order - 1 ); if ( even( order ) ) { a += SolidAngle(); } return a / ( order + 1 ); }
f32 Rectangle::IntegrateMRP( const vec3f & integrationPos, const vec3f & integrationNrm ) const { const vec3f d0p = -ez; const vec3f d1p = integrationNrm; const f32 nDotpN = std::max( 0.f, Dot( integrationNrm, ez ) ); vec3f d0 = Normalize( d0p + integrationNrm * nDotpN ); vec3f d1 = Normalize( d1p - ez * nDotpN ); vec3f dh = Normalize( d0 + d1 ); Plane rectPlane = { position, ez }; vec3f pH = rectPlane.RayIntersection( integrationPos, dh ); pH = rectPlane.ClampPointInRect( *this, pH ); const f32 solidAngle = SolidAngle( integrationPos ); vec3f rayDir = Normalize( pH - integrationPos ); return solidAngle * std::max( 0.f, Dot( integrationNrm, rayDir ) ); }
void Polygon::AxialMoment( const vec3f &w, int order, std::vector<f32> &R ) const { // Compute the Boundary Integral of the polygon BoundaryIntegral( w, w, order, R ); // - boundary + solidangle for even orders f32 sA = SolidAngle(); for ( u32 i = 0; i < R.size(); ++i ) { R[i] *= -1.f; // - boundary // add the solid angle for even orders if ( even( i ) ) { R[i] += sA; } // normalize by order+1 R[i] *= -1.f / (f32) ( i + 1 ); } }
SolidAngle SolidAngle::operator-(const SolidAngle& rhs) const { return SolidAngle( mSolidAngle - rhs.mSolidAngle ); }
namespace Sirikata { const float SolidAngle::Pi = 3.1415926536f; const float SolidAngle::MinVal = 0.0f; const float SolidAngle::MaxVal = 4.0f*SolidAngle::Pi; const SolidAngle SolidAngle::Min = SolidAngle(SolidAngle::MinVal); const SolidAngle SolidAngle::Max = SolidAngle(SolidAngle::MaxVal); SolidAngle::SolidAngle() : mSolidAngle(MinVal) { } SolidAngle::SolidAngle(float sa) : mSolidAngle(sa) { clamp(); } SolidAngle::SolidAngle(const SolidAngle& rhs) : mSolidAngle(rhs.mSolidAngle) { } SolidAngle::~SolidAngle() { } float SolidAngle::asFloat() const { return mSolidAngle; } SolidAngle SolidAngle::fromCenterRadius(const Vector3<float>& to_center, float radius) { float to_center_len = to_center.length(); if (to_center_len <= radius) return SolidAngle(MaxVal); float sin_alpha = radius / to_center_len; float cos_alpha = sqrtf(1 - sin_alpha*sin_alpha); return SolidAngle( 2.0f * Pi * (1.0f - cos_alpha) ); } float SolidAngle::maxDistance(float obj_radius) const { float C = 1.f - mSolidAngle / (2.0f * SolidAngle::Pi); C = 1.f - C*C; return obj_radius / sqrtf(C); } SolidAngle SolidAngle::operator+(const SolidAngle& rhs) const { return SolidAngle( mSolidAngle + rhs.mSolidAngle ); } SolidAngle& SolidAngle::operator+=(const SolidAngle& rhs) { mSolidAngle += rhs.mSolidAngle; clamp(); return *this; } SolidAngle SolidAngle::operator-(const SolidAngle& rhs) const { return SolidAngle( mSolidAngle - rhs.mSolidAngle ); } SolidAngle& SolidAngle::operator-=(const SolidAngle& rhs) { mSolidAngle -= rhs.mSolidAngle; clamp(); return *this; } SolidAngle SolidAngle::operator*(float rhs) const { assert(rhs >= 0.f); return SolidAngle( mSolidAngle * rhs ); } SolidAngle& SolidAngle::operator*=(float rhs) { assert(rhs >= 0.f); mSolidAngle *= rhs; clamp(); return *this; } SolidAngle SolidAngle::operator/(float rhs) const { assert(rhs > 0.f); return SolidAngle( mSolidAngle / rhs ); } SolidAngle& SolidAngle::operator/=(float rhs) { assert(rhs > 0.f); mSolidAngle /= rhs; clamp(); return *this; } bool SolidAngle::operator<(const SolidAngle& rhs) const { return (mSolidAngle < rhs.mSolidAngle); } bool SolidAngle::operator==(const SolidAngle& rhs) const { return (mSolidAngle == rhs.mSolidAngle); } bool SolidAngle::operator<=(const SolidAngle& rhs) const { return (mSolidAngle <= rhs.mSolidAngle); } bool SolidAngle::operator>(const SolidAngle& rhs) const { return (mSolidAngle > rhs.mSolidAngle); } bool SolidAngle::operator>=(const SolidAngle& rhs) const { return (mSolidAngle >= rhs.mSolidAngle); } bool SolidAngle::operator!=(const SolidAngle& rhs) const { return (mSolidAngle != rhs.mSolidAngle); } void SolidAngle::clamp() { if (mSolidAngle < MinVal) mSolidAngle = MinVal; if (mSolidAngle > MaxVal) mSolidAngle = MaxVal; } std::ostream& operator<< (std::ostream &os, const Sirikata::SolidAngle& output) { os << output.asFloat() << "sr"; return os; } } // namespace Sirikata
SolidAngle SolidAngle::operator/(float rhs) const { assert(rhs > 0.f); return SolidAngle( mSolidAngle / rhs ); }
SolidAngle SolidAngle::operator*(float rhs) const { assert(rhs >= 0.f); return SolidAngle( mSolidAngle * rhs ); }