GfRay GfFrustum::ComputeRay(const GfVec3d &worldSpacePos) const { GfVec3d camSpaceToPos = ComputeViewMatrix().Transform(worldSpacePos); // Compute the camera-space starting point (the viewpoint) and // direction (toward the point camSpaceToPos). GfVec3d pos; GfVec3d dir; if (_projectionType == Perspective) { pos = GfVec3d(0); dir = camSpaceToPos.GetNormalized(); } else { pos.Set(camSpaceToPos[0], camSpaceToPos[1], 0.0); dir = -GfVec3d::ZAxis(); } // Transform these by the inverse of the view matrix. const GfMatrix4d &viewInverse = ComputeViewInverse(); GfVec3d rayFrom = viewInverse.Transform(pos); GfVec3d rayDir = viewInverse.TransformDir(dir); // Build and return the ray return GfRay(rayFrom, rayDir); }
static GfRay _ComputeUntransformedRay(GfFrustum::ProjectionType projectionType, const GfRange2d &window, const GfVec2d &windowPos) { // Compute position on window, from provided normalized // (-1 to 1) coordinates. double winX = _Rescale(windowPos[0], -1.0, 1.0, window.GetMin()[0], window.GetMax()[0]); double winY = _Rescale(windowPos[1], -1.0, 1.0, window.GetMin()[1], window.GetMax()[1]); // Compute the camera-space starting point (the viewpoint) and // direction (toward the point on the window). GfVec3d pos; GfVec3d dir; if (projectionType == GfFrustum::Perspective) { pos = GfVec3d(0); dir = GfVec3d(winX, winY, -1.0).GetNormalized(); } else { pos.Set(winX, winY, 0.0); dir = -GfVec3d::ZAxis(); } // Build and return the ray return GfRay(pos, dir); }
GfRay GfFrustum::ComputePickRay(const GfVec3d &worldSpacePos) const { GfVec3d camSpaceToPos = ComputeViewMatrix().Transform(worldSpacePos); // Compute the camera-space starting point (the viewpoint) and // direction (toward the point camSpaceToPos). GfVec3d pos; GfVec3d dir; if (_projectionType == Perspective) { pos = GfVec3d(0); dir = camSpaceToPos.GetNormalized(); } else { pos.Set(camSpaceToPos[0], camSpaceToPos[1], 0.0); dir = -GfVec3d::ZAxis(); } return _ComputePickRayOffsetToNearPlane(pos, dir); }
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); }
bool GfRay::Intersect(const GfVec3d &origin, const GfVec3d &axis, const double radius, const double height, double *enterDistance, double *exitDistance) const { GfVec3d unitAxis = axis.GetNormalized(); // Apex of cone GfVec3d apex = origin + height * unitAxis; GfVec3d delta = _startPoint - apex; GfVec3d u =_direction - GfDot(_direction, unitAxis) * unitAxis; GfVec3d v = delta - GfDot(delta, unitAxis) * unitAxis; double p = GfDot(_direction, unitAxis); double q = GfDot(delta, unitAxis); double cos2 = GfSqr(height) / (GfSqr(height) + GfSqr(radius)); double sin2 = 1 - cos2; double a = cos2 * GfDot(u, u) - sin2 * GfSqr(p); double b = 2.0 * (cos2 * GfDot(u, v) - sin2 * p * q); double c = cos2 * GfDot(v, v) - sin2 * GfSqr(q); if (!_SolveQuadratic(a, b, c, enterDistance, exitDistance)) { return false; } // Eliminate any solutions on the double cone bool enterValid = GfDot(unitAxis, GetPoint(*enterDistance) - apex) <= 0.0; bool exitValid = GfDot(unitAxis, GetPoint(*exitDistance) - apex) <= 0.0; if ((!enterValid) && (!exitValid)) { // Solutions lie only on double cone return false; } if (!enterValid) { *enterDistance = *exitDistance; } else if (!exitValid) { *exitDistance = *enterDistance; } return true; }
bool GfRay::Intersect(const GfVec3d &origin, const GfVec3d &axis, const double radius, double *enterDistance, double *exitDistance) const { GfVec3d unitAxis = axis.GetNormalized(); GfVec3d delta = _startPoint - origin; GfVec3d u = _direction - GfDot(_direction, unitAxis) * unitAxis; GfVec3d v = delta - GfDot(delta, unitAxis) * unitAxis; // Quadratic equation for implicit infinite cylinder double a = GfDot(u, u); double b = 2.0 * GfDot(u, v); double c = GfDot(v, v) - GfSqr(radius); return _SolveQuadratic(a, b, c, enterDistance, exitDistance); }
GfFrustum & GfFrustum::Transform(const GfMatrix4d &matrix) { // We'll need the old parameters as we build up the new ones, so, work // on a newly instantiated frustum. We'll replace the contents of // this frustum with it once we are done. Note that _dirty is true // by default, so, there is no need to initialize it here. GfFrustum frustum; // Copy the projection type frustum._projectionType = _projectionType; // Transform the position of the frustum frustum._position = matrix.Transform(_position); // Transform the rotation as follows: // 1. build view and direction vectors // 2. transform them with the given matrix // 3. normalize the vectors and cross them to build an orthonormal frame // 4. construct a rotation matrix // 5. extract the new rotation from the matrix // Generate view direction and up vector GfVec3d viewDir = ComputeViewDirection(); GfVec3d upVec = ComputeUpVector(); // Transform by matrix GfVec3d viewDirPrime = matrix.TransformDir(viewDir); GfVec3d upVecPrime = matrix.TransformDir(upVec); // Normalize. Save the vec size since it will be used to scale near/far. double scale = viewDirPrime.Normalize(); upVecPrime.Normalize(); // Cross them to get the third axis. Voila. We have an orthonormal frame. GfVec3d viewRightPrime = GfCross(viewDirPrime, upVecPrime); viewRightPrime.Normalize(); // Construct a rotation matrix using the axes. // // [ right 0 ] // [ up 1 ] // [ -viewDir 0 ] // [ 0 0 0 1 ] GfMatrix4d rotMatrix; rotMatrix.SetIdentity(); // first row rotMatrix[0][0] = viewRightPrime[0]; rotMatrix[0][1] = viewRightPrime[1]; rotMatrix[0][2] = viewRightPrime[2]; // second row rotMatrix[1][0] = upVecPrime[0]; rotMatrix[1][1] = upVecPrime[1]; rotMatrix[1][2] = upVecPrime[2]; // third row rotMatrix[2][0] = -viewDirPrime[0]; rotMatrix[2][1] = -viewDirPrime[1]; rotMatrix[2][2] = -viewDirPrime[2]; // Extract rotation frustum._rotation = rotMatrix.ExtractRotation(); // Since we applied the matrix to the direction vector, we can use // its length to find out the scaling that needs to applied to the // near and far plane. frustum._nearFar = _nearFar * scale; // Use the same length to scale the view distance frustum._viewDistance = _viewDistance * scale; // Transform the reference plane as follows: // // - construct two 3D points that are on the reference plane // (left/bottom and right/top corner of the reference window) // - transform the points with the given matrix // - move the window back to one unit from the viewpoint and // extract the 2D coordinates that would form the new reference // window // // A note on how we do the last "move" of the reference window: // Using similar triangles and the fact that the reference window // is one unit away from the viewpoint, one can show that it's // sufficient to divide the x and y components of the transformed // corners by the length of the transformed direction vector. // // A 2D diagram helps: // // | // | // | | // * ------+------------+ // vp |y1 | // | // \--d1--/ |y2 // // \-------d2----------/ // // So, y1/y2 = d1/d2 ==> y1 = y2 * d1/d2 // Since d1 = 1 ==> y1 = y2 / d2 // The same argument applies to the x coordinate. // // NOTE: In an orthographic projection, the last step (division by // the length of the vector) is skipped. // // XXX NOTE2: The above derivation relies on the // fact that GetReferecePlaneDepth() is 1.0. // If we ever allow this to NOT be 1, we'll need to fix this up. const GfVec2d &min = _window.GetMin(); const GfVec2d &max = _window.GetMax(); // Construct the corner points in 3D as follows: construct a starting // point by using the x and y coordinates of the reference plane and // -1 as the z coordinate. Add the position of the frustum to generate // the actual points in world-space coordinates. GfVec3d leftBottom = _position + _rotation.TransformDir(GfVec3d(min[0], min[1], -1.0)); GfVec3d rightTop = _position + _rotation.TransformDir(GfVec3d(max[0], max[1], -1.0)); // Now, transform the corner points by the given matrix leftBottom = matrix.Transform(leftBottom); rightTop = matrix.Transform(rightTop); // Subtract the transformed frustum position from the transformed // corner points. Then, rotate the points using the rotation that would // transform the view direction vector back to (0, 0, -1). This brings // the corner points from the woorld coordinate system into the local // frustum one. leftBottom -= frustum._position; rightTop -= frustum._position; leftBottom = frustum._rotation.GetInverse().TransformDir(leftBottom); rightTop = frustum._rotation.GetInverse().TransformDir(rightTop); // Finally, use the similar triangles trick to bring the corner // points back at one unit away from the point. These scaled x and // y coordinates can be directly used to construct the new // transformed reference plane. Skip the scaling step for an // orthographic projection, though. if (_projectionType == Perspective) { leftBottom /= scale; rightTop /= scale; } frustum._window.SetMin(GfVec2d(leftBottom[0], leftBottom[1])); frustum._window.SetMax(GfVec2d(rightTop[0], rightTop[1])); // Note that negative scales in the transform have the potential // to flip the window. Fix it if necessary. GfVec2d wMin = frustum._window.GetMin(); GfVec2d wMax = frustum._window.GetMax(); // Make sure left < right if ( wMin[0] > wMax[0] ) { std::swap( wMin[0], wMax[0] ); } // Make sure bottom < top if ( wMin[1] > wMax[1] ) { std::swap( wMin[1], wMax[1] ); } frustum._window.SetMin( wMin ); frustum._window.SetMax( wMax ); *this = frustum; return *this; }
/* static */ GT_DataArrayHandle GusdPrimWrapper::convertPrimvarData( const UsdGeomPrimvar& primvar, UsdTimeCode time ) { SdfValueTypeName typeName = primvar.GetTypeName(); if( typeName == SdfValueTypeNames->Int ) { int usdVal; primvar.Get( &usdVal, time ); return new GT_Int32Array( &usdVal, 1, 1 ); } else if( typeName == SdfValueTypeNames->Int64 ) { int64_t usdVal; primvar.Get( &usdVal, time ); return new GT_Int64Array( &usdVal, 1, 1 ); } else if( typeName == SdfValueTypeNames->Float ) { float usdVal; primvar.Get( &usdVal, time ); return new GT_Real32Array( &usdVal, 1, 1 ); } else if( typeName == SdfValueTypeNames->Double ) { double usdVal; primvar.Get( &usdVal, time ); return new GT_Real64Array( &usdVal, 1, 1 ); } else if( typeName == SdfValueTypeNames->Float3 ) { GfVec3f usdVal; primvar.Get( &usdVal, time ); return new GT_Real32Array( usdVal.data(), 1, 3 ); } else if( typeName == SdfValueTypeNames->Double3 ) { GfVec3d usdVal; primvar.Get( &usdVal, time ); return new GT_Real64Array( usdVal.data(), 1, 3 ); } else if( typeName == SdfValueTypeNames->Color3f ) { GfVec3f usdVal; primvar.Get( &usdVal, time ); return new GT_Real32Array( usdVal.data(), 1, 3, GT_TYPE_COLOR ); } else if( typeName == SdfValueTypeNames->Color3d ) { GfVec3d usdVal; primvar.Get( &usdVal, time ); return new GT_Real64Array( usdVal.data(), 1, 3, GT_TYPE_COLOR ); } else if( typeName == SdfValueTypeNames->Normal3f ) { GfVec3f usdVal; primvar.Get( &usdVal, time ); return new GT_Real32Array( usdVal.data(), 1, 3, GT_TYPE_NORMAL ); } else if( typeName == SdfValueTypeNames->Normal3d ) { GfVec3d usdVal; primvar.Get( &usdVal, time ); return new GT_Real64Array( usdVal.data(), 1, 3, GT_TYPE_NORMAL ); } else if( typeName == SdfValueTypeNames->Point3f ) { GfVec3f usdVal; primvar.Get( &usdVal, time ); return new GT_Real32Array( usdVal.data(), 1, 3, GT_TYPE_POINT ); } else if( typeName == SdfValueTypeNames->Point3d ) { GfVec3d usdVal; primvar.Get( &usdVal, time ); return new GT_Real64Array( usdVal.data(), 1, 3, GT_TYPE_POINT ); } else if( typeName == SdfValueTypeNames->Float4 ) { GfVec4f usdVal; primvar.Get( &usdVal, time ); return new GT_Real32Array( usdVal.data(), 1, 4 ); } else if( typeName == SdfValueTypeNames->Double4 ) { GfVec4d usdVal; primvar.Get( &usdVal, time ); return new GT_Real64Array( usdVal.data(), 1, 4 ); } else if( typeName == SdfValueTypeNames->Quatf ) { GfVec4f usdVal; primvar.Get( &usdVal, time ); return new GT_Real32Array( usdVal.data(), 1, 4, GT_TYPE_QUATERNION ); } else if( typeName == SdfValueTypeNames->Quatd ) { GfVec4d usdVal; primvar.Get( &usdVal, time ); return new GT_Real64Array( usdVal.data(), 1, 4, GT_TYPE_QUATERNION ); } else if( typeName == SdfValueTypeNames->Matrix3d ) { GfMatrix3d usdVal; primvar.Get( &usdVal, time ); return new GT_Real64Array( usdVal.GetArray(), 1, 9, GT_TYPE_MATRIX3 ); } else if( typeName == SdfValueTypeNames->Matrix4d || typeName == SdfValueTypeNames->Frame4d ) { GfMatrix4d usdVal; primvar.Get( &usdVal, time ); return new GT_Real64Array( usdVal.GetArray(), 1, 16, GT_TYPE_MATRIX ); } else if( typeName == SdfValueTypeNames->String ) { string usdVal; primvar.Get( &usdVal, time ); auto gtString = new GT_DAIndexedString( 1 ); gtString->setString( 0, 0, usdVal.c_str() ); return gtString; } else if( typeName == SdfValueTypeNames->StringArray ) { VtArray<string> usdVal; primvar.ComputeFlattened( &usdVal, time ); auto gtString = new GT_DAIndexedString( usdVal.size() ); for( size_t i = 0; i < usdVal.size(); ++i ) gtString->setString( i, 0, usdVal[i].c_str() ); return gtString; } else if( typeName == SdfValueTypeNames->IntArray ) { VtArray<int> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<int>(usdVal); } else if( typeName == SdfValueTypeNames->Int64Array ) { VtArray<int64_t> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<int64_t>(usdVal); } else if( typeName == SdfValueTypeNames->FloatArray ) { VtArray<float> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<float>(usdVal); } else if( typeName == SdfValueTypeNames->DoubleArray ) { VtArray<double> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<double>(usdVal); } else if( typeName == SdfValueTypeNames->Float2Array ) { VtArray<GfVec2f> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec2f>(usdVal); } else if( typeName == SdfValueTypeNames->Double2Array ) { VtArray<GfVec2d> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec2d>(usdVal); } else if( typeName == SdfValueTypeNames->Float3Array ) { VtArray<GfVec3f> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec3f>(usdVal); } else if( typeName == SdfValueTypeNames->Double3Array ) { VtArray<GfVec3d> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec3d>(usdVal); } else if( typeName == SdfValueTypeNames->Color3fArray ) { VtArray<GfVec3f> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec3f>(usdVal,GT_TYPE_COLOR); } else if( typeName == SdfValueTypeNames->Color3dArray ) { VtArray<GfVec3d> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec3d>(usdVal,GT_TYPE_COLOR); } else if( typeName == SdfValueTypeNames->Vector3fArray ) { VtArray<GfVec3f> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec3f>(usdVal, GT_TYPE_VECTOR); } else if( typeName == SdfValueTypeNames->Vector3dArray ) { VtArray<GfVec3d> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec3d>(usdVal, GT_TYPE_VECTOR); } else if( typeName == SdfValueTypeNames->Normal3fArray ) { VtArray<GfVec3f> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec3f>(usdVal, GT_TYPE_NORMAL); } else if( typeName == SdfValueTypeNames->Normal3dArray ) { VtArray<GfVec3d> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec3d>(usdVal, GT_TYPE_NORMAL); } else if( typeName == SdfValueTypeNames->Point3fArray ) { VtArray<GfVec3f> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec3f>(usdVal, GT_TYPE_POINT); } else if( typeName == SdfValueTypeNames->Point3dArray ) { VtArray<GfVec3d> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec3d>(usdVal, GT_TYPE_POINT); } else if( typeName == SdfValueTypeNames->Float4Array ) { VtArray<GfVec4f> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec4f>(usdVal); } else if( typeName == SdfValueTypeNames->Double4Array ) { VtArray<GfVec4d> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec4d>(usdVal); } else if( typeName == SdfValueTypeNames->QuatfArray ) { VtArray<GfVec4f> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec4f>(usdVal, GT_TYPE_QUATERNION); } else if( typeName == SdfValueTypeNames->QuatdArray ) { VtArray<GfVec4d> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfVec4d>(usdVal, GT_TYPE_QUATERNION); } else if( typeName == SdfValueTypeNames->Matrix3dArray ) { VtArray<GfMatrix3d> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfMatrix3d>(usdVal, GT_TYPE_MATRIX3); } else if( typeName == SdfValueTypeNames->Matrix4dArray || typeName == SdfValueTypeNames->Frame4dArray ) { VtArray<GfMatrix4d> usdVal; primvar.ComputeFlattened( &usdVal, time ); return new GusdGT_VtArray<GfMatrix4d>(usdVal, GT_TYPE_MATRIX); } return NULL; }
void GfPlane::Set(const GfVec3d &normal, const GfVec3d &point) { _normal = normal.GetNormalized(); _distance = GfDot(_normal, point); }