bool GfFindClosestPoints( const GfLineSeg &seg1, const GfLineSeg &seg2, GfVec3d *p1, GfVec3d *p2, double *t1, double *t2 ) { GfVec3d cp1, cp2; double lt1, lt2; if ( !GfFindClosestPoints( seg1._line, seg2._line, &cp1, &cp2, <1, <2 ) ) return false; lt1 = GfClamp( lt1 / seg1._length, 0, 1 ); lt2 = GfClamp( lt2 / seg2._length, 0, 1 ); if ( p1 ) *p1 = seg1.GetPoint( lt1 ); if ( p2 ) *p2 = seg2.GetPoint( lt2 ); if ( t1 ) *t1 = lt1; if ( t2 ) *t2 = lt2; return true; }
GfRGB GfRGB::GetOffsetFromColor(const GfRGB &offsetBase, const GfRGB &offsetColor) { GfRGB offsetHSV; // Convert offsetBase and offsetColor to HSV space GfRGB offsetBaseHSV, offsetColorHSV; offsetBase.GetHSV(&offsetBaseHSV[0], &offsetBaseHSV[1], &offsetBaseHSV[2]); offsetColor.GetHSV(&offsetColorHSV[0], &offsetColorHSV[1], &offsetColorHSV[2]); // Determine the offset for each component in HSV space for (int c = 0; c < 3; ++c) { // For sanity float baseC = GfClamp(offsetBaseHSV[c], 0, 1); float offC = GfClamp(offsetColorHSV[c], 0, 1); float delta = offC - baseC; if (delta > 0) // baseC must be < 1 for delta > 0 offsetHSV[c] = delta / (1 - baseC); else if (delta < 0) // baseC must be > 0 for delta < 0 offsetHSV[c] = delta / baseC; else // delta == 0 offsetHSV[c] = 0; } return offsetHSV; }
// Offsets are kinda funky. Essentially each component of an offset is // a scaling term which says how far a component should be changed and in // what direction. An offset of 0.5, for example, moves its component 50% // of the distance between the base value and its maximum value in the // positive direction, whereas an offset of -0.1 moves its component 10% of // the distance between its base value and its minimum value in the negative // direction. // GfRGB GfRGB::GetColorFromOffset(const GfRGB &offsetBase, const GfRGB &offsetHSV) { GfRGB offsetBaseHSV, offsetColorHSV; // Convert base to HSV space offsetBase.GetHSV(&offsetBaseHSV[0], &offsetBaseHSV[1], &offsetBaseHSV[2]); // Offset each component of base in HSV space for (int c = 0; c < 3; ++c) { // For sanity float baseC = GfClamp(offsetBaseHSV[c], 0, 1); float off = GfClamp(offsetHSV[c], -1, 1); offsetColorHSV[c] = baseC + off * (off > 0 ? 1 - baseC : baseC); } // Convert offsetColorHSV to RGB space GfRGB offsetColor; offsetColor.SetHSV(offsetColorHSV[0], offsetColorHSV[1], offsetColorHSV[2]); return offsetColor; }
GlfSimpleLight HdStLight::_ApproximateAreaLight(SdfPath const &id, HdSceneDelegate *sceneDelegate) { // Get the color of the light GfVec3f hdc = sceneDelegate->GetLightParamValue(id, HdStLightTokens->color) .Get<GfVec3f>(); // Extract intensity float intensity = sceneDelegate->GetLightParamValue(id, HdLightTokens->intensity) .Get<float>(); // Extract the exposure of the light float exposure = sceneDelegate->GetLightParamValue(id, HdLightTokens->exposure) .Get<float>(); intensity *= powf(2.0f, GfClamp(exposure, -50.0f, 50.0f)); // Calculate the final color of the light GfVec4f c(hdc[0]*intensity, hdc[1]*intensity, hdc[2]*intensity, 1.0f); // Get the transform of the light GfMatrix4d transform = _params[HdTokens->transform].Get<GfMatrix4d>(); GfVec3d hdp = transform.ExtractTranslation(); GfVec4f p = GfVec4f(hdp[0], hdp[1], hdp[2], 1.0f); // Create the Glf Simple Light object that will be used by the rest // of the pipeline. No support for shadows for this translated light. GlfSimpleLight l; l.SetPosition(p); l.SetDiffuse(c); l.SetHasShadow(false); return l; }
bool GfFindClosestPoints( const GfLine &line, const GfLineSeg &seg, GfVec3d *p1, GfVec3d *p2, double *t1, double *t2 ) { GfVec3d cp1, cp2; double lt1, lt2; if ( !GfFindClosestPoints( line, seg._line, &cp1, &cp2, <1, <2 ) ) return false; lt2 = GfClamp( lt2 / seg._length, 0, 1 ); cp2 = seg.GetPoint( lt2 ); // If we clamp the line segment, change the rayPoint to be // the closest point on the ray to the clamped point. if (lt2 <= 0 || lt2 >= 1){ cp1 = line.FindClosestPoint(cp2, <1); } if ( p1 ) *p1 = cp1; if ( p2 ) *p2 = cp2; if ( t1 ) *t1 = lt1; if ( t2 ) *t2 = lt2; return true; }
GfQuaternion GfMatrix3d::ExtractRotationQuaternion() const { // This was adapted from the (open source) Open Inventor // SbRotation::SetValue(const SbMatrix &m) int i; // First, find largest diagonal in matrix: if (_mtx[0][0] > _mtx[1][1]) i = (_mtx[0][0] > _mtx[2][2] ? 0 : 2); else i = (_mtx[1][1] > _mtx[2][2] ? 1 : 2); GfVec3d im; double r; if (_mtx[0][0] + _mtx[1][1] + _mtx[2][2] > _mtx[i][i]) { r = 0.5 * sqrt(_mtx[0][0] + _mtx[1][1] + _mtx[2][2] + 1); im.Set((_mtx[1][2] - _mtx[2][1]) / (4.0 * r), (_mtx[2][0] - _mtx[0][2]) / (4.0 * r), (_mtx[0][1] - _mtx[1][0]) / (4.0 * r)); } else { int j = (i + 1) % 3; int k = (i + 2) % 3; double q = 0.5 * sqrt(_mtx[i][i] - _mtx[j][j] - _mtx[k][k] + 1); im[i] = q; im[j] = (_mtx[i][j] + _mtx[j][i]) / (4 * q); im[k] = (_mtx[k][i] + _mtx[i][k]) / (4 * q); r = (_mtx[j][k] - _mtx[k][j]) / (4 * q); } return GfQuaternion(GfClamp(r, -1.0, 1.0), im); }
GfVec3d GfLineSeg::FindClosestPoint(const GfVec3d &point, double *t) const { // Find the parametric distance, lt, of the closest point on the line // and then clamp lt to be on the line segment. double lt; if ( _length == 0.0 ) { lt = 0.0; } else { _line.FindClosestPoint( point, < ); lt = GfClamp( lt / _length, 0, 1 ); } if ( t ) *t = lt; return GetPoint( lt ); }
GfVec3f GfSlerp(double alpha, const GfVec3f &v0, const GfVec3f &v1) { // determine the angle between the two lines going from the center of // the sphere to v0 and v1. the projection (dot prod) of one onto the // other gives us the arc cosine of the angle between them. double angle = acos(GfClamp((double)GfDot(v0, v1), -1.0, 1.0)); // Check for very small angle between the vectors, and if so, just lerp them. // XXX: This value for epsilon is somewhat arbitrary, and if // someone can derive a more meaningful value, that would be fine. if ( fabs(angle) < 0.001 ) { return GfLerp(alpha, v0, v1); } // compute the sin of the angle, we need it a couple of places double sinAngle = sin(angle); // Check if the vectors are nearly opposing, and if so, // compute an arbitrary orthogonal vector to interpolate across. // XXX: Another somewhat arbitrary test for epsilon, but trying to stay // within reasonable float precision. if ( fabs(sinAngle) < 0.00001 ) { GfVec3f vX, vY; v0.BuildOrthonormalFrame(&vX, &vY); GfVec3f v = v0 * cos(alpha*M_PI) + vX * sin(alpha*M_PI); return v; } // interpolate double oneOverSinAngle = 1.0 / sinAngle; return v0 * (sin((1.0-alpha)*angle) * oneOverSinAngle) + v1 * (sin( alpha *angle) * oneOverSinAngle); }