float GfCamera::GetFieldOfView(FOVDirection direction) const { // Pick the right aperture based on direction const float aperture = (direction == FOVHorizontal) ? _horizontalAperture : _verticalAperture; // Do the math const float fovRAD = 2 * atan( (aperture * GfCamera::APERTURE_UNIT) / (2 * _focalLength * GfCamera::FOCAL_LENGTH_UNIT)); return GfRadiansToDegrees(fovRAD); }
// For a given GeomXForm and array of AnimChannels and time, compute the data // from if needed and set the XFormOps values static void computeXFormOps( const UsdGeomXformable& usdXformable, const std::vector<AnimChannel>& animChanList, const UsdTimeCode &usdTime) { // Iterate over each AnimChannel, retrieve the default value and pull the // Maya data if needed. Then store it on the USD Ops for (unsigned int channelIdx = 0; channelIdx < animChanList.size(); ++channelIdx) { const AnimChannel& animChannel = animChanList[channelIdx]; if (animChannel.isInverse) { continue; } GfVec3d value = animChannel.defValue; bool hasAnimated = false, hasStatic = false; for (unsigned int i = 0; i<3; i++) { if (animChannel.sampleType[i] == ANIMATED) { // NOTE the default value has already been converted to // radians. double chanVal = animChannel.plug[i].asDouble(); value[i] = animChannel.opType == ROTATE ? GfRadiansToDegrees(chanVal) : chanVal; hasAnimated = true; } else if (animChannel.sampleType[i] == STATIC) { hasStatic = true; } } // If the channel is not animated AND has non identity value, we are // computing default time, then set the values. // // If the channel is animated(connected) and we are not setting default // time, then set the values. // // This to make sure static channels are setting their default while // animating ones are actually animating if ((usdTime == UsdTimeCode::Default() && hasStatic && !hasAnimated) || (usdTime != UsdTimeCode::Default() && hasAnimated)) { setXformOp(animChannel.op, value, usdTime); } } }
// Creates an AnimChannel from a Maya compound attribute if there is meaningful // data. This means we found data that is non-identity. // // returns true if we extracted an AnimChannel and false otherwise (e.g., the // data was identity). static bool _GatherAnimChannel( XFormOpType opType, const MFnTransform& iTrans, MString parentName, MString xName, MString yName, MString zName, std::vector<AnimChannel>* oAnimChanList, bool isWritingAnimation, bool setOpName) { AnimChannel chan; chan.opType = opType; chan.isInverse = false; if (setOpName) { chan.opName = parentName.asChar(); } // We default to single precision (later we set the main translate op and // shear to double) chan.precision = UsdGeomXformOp::PrecisionFloat; unsigned int validComponents = 0; // this is to handle the case where there is a connection to the parent // plug but not to the child plugs, if the connection is there and you are // not forcing static, then all of the children are considered animated int parentSample = PxrUsdMayaUtil::getSampledType(iTrans.findPlug(parentName),false); // Determine what plug are needed based on default value & being // connected/animated MStringArray channels; channels.append(parentName+xName); channels.append(parentName+yName); channels.append(parentName+zName); GfVec3d nullValue(opType == SCALE ? 1.0 : 0.0); for (unsigned int i = 0; i<3; i++) { // Find the plug and retrieve the data as the channel default value. It // won't be updated if the channel is NOT ANIMATED chan.plug[i] = iTrans.findPlug(channels[i]); double plugValue = chan.plug[i].asDouble(); chan.defValue[i] = opType == ROTATE ? GfRadiansToDegrees(plugValue) : plugValue; chan.sampleType[i] = NO_XFORM; // If we allow animation and either the parentsample or local sample is // not 0 then we havea ANIMATED sample else we have a scale and the // value is NOT 1 or if the value is NOT 0 then we have a static xform if ((parentSample != 0 || PxrUsdMayaUtil::getSampledType(chan.plug[i], true) != 0) && isWritingAnimation) { chan.sampleType[i] = ANIMATED; validComponents++; } else if (!GfIsClose(chan.defValue[i], nullValue[i], 1e-7)) { chan.sampleType[i] = STATIC; validComponents++; } } // If there are valid component, then we will add the animation channel. // Rotates with 1 component will be optimized to single axis rotation if (validComponents>0) { if (opType == SCALE) { chan.usdOpType = UsdGeomXformOp::TypeScale; } else if (opType == TRANSLATE) { chan.usdOpType = UsdGeomXformOp::TypeTranslate; // The main translate is set to double precision if (parentName == "translate") { chan.precision = UsdGeomXformOp::PrecisionDouble; } } else if (opType == ROTATE) { chan.usdOpType = UsdGeomXformOp::TypeRotateXYZ; if (validComponents == 1) { if (chan.sampleType[0] != NO_XFORM) chan.usdOpType = UsdGeomXformOp::TypeRotateX; if (chan.sampleType[1] != NO_XFORM) chan.usdOpType = UsdGeomXformOp::TypeRotateY; if (chan.sampleType[2] != NO_XFORM) chan.usdOpType = UsdGeomXformOp::TypeRotateZ; } else { // Rotation Order ONLY applies to the "rotate" attribute if (parentName == "rotate") { switch (iTrans.rotationOrder()) { case MTransformationMatrix::kYZX: chan.usdOpType = UsdGeomXformOp::TypeRotateYZX; break; case MTransformationMatrix::kZXY: chan.usdOpType = UsdGeomXformOp::TypeRotateZXY; break; case MTransformationMatrix::kXZY: chan.usdOpType = UsdGeomXformOp::TypeRotateXZY; break; case MTransformationMatrix::kYXZ: chan.usdOpType = UsdGeomXformOp::TypeRotateYXZ; break; case MTransformationMatrix::kZYX: chan.usdOpType = UsdGeomXformOp::TypeRotateZYX; break; default: break; } } } } else if (opType == SHEAR) { chan.usdOpType = UsdGeomXformOp::TypeTransform; chan.precision = UsdGeomXformOp::PrecisionDouble; } else { return false; } oAnimChanList->push_back(chan); return true; } return false; }
/* static */ GlfSimpleLightingContextRefPtr px_vp20Utils::GetLightingContextFromDrawContext( const MHWRender::MDrawContext& context) { const GfVec4f blackColor(0.0f, 0.0f, 0.0f, 1.0f); const GfVec4f whiteColor(1.0f, 1.0f, 1.0f, 1.0f); GlfSimpleLightingContextRefPtr lightingContext = GlfSimpleLightingContext::New(); MStatus status; unsigned int numMayaLights = context.numberOfActiveLights(MHWRender::MDrawContext::kFilteredToLightLimit, &status); if (status != MS::kSuccess || numMayaLights < 1) { return lightingContext; } bool viewDirectionAlongNegZ = context.viewDirectionAlongNegZ(&status); if (status != MS::kSuccess) { // If we fail to find out the view direction for some reason, assume // that it's along the negative Z axis (OpenGL). viewDirectionAlongNegZ = true; } GlfSimpleLightVector lights; for (unsigned int i = 0; i < numMayaLights; ++i) { MHWRender::MLightParameterInformation* mayaLightParamInfo = context.getLightParameterInformation(i); if (!mayaLightParamInfo) { continue; } // Setup some default values before we read the light parameters. bool lightEnabled = true; bool lightHasPosition = false; GfVec4f lightPosition(0.0f, 0.0f, 0.0f, 1.0f); bool lightHasDirection = false; GfVec3f lightDirection(0.0f, 0.0f, -1.0f); if (!viewDirectionAlongNegZ) { // The convention for DirectX is positive Z. lightDirection[2] = 1.0f; } float lightIntensity = 1.0f; GfVec4f lightColor = blackColor; bool lightEmitsDiffuse = true; bool lightEmitsSpecular = false; float lightDecayRate = 0.0f; float lightDropoff = 0.0f; // The cone angle is 180 degrees by default. GfVec2f lightCosineConeAngle(-1.0f); float lightShadowBias = 0.0f; bool lightShadowOn = false; bool globalShadowOn = false; MStringArray paramNames; mayaLightParamInfo->parameterList(paramNames); for (unsigned int paramIndex = 0; paramIndex < paramNames.length(); ++paramIndex) { const MString paramName = paramNames[paramIndex]; const MHWRender::MLightParameterInformation::ParameterType paramType = mayaLightParamInfo->parameterType(paramName); const MHWRender::MLightParameterInformation::StockParameterSemantic paramSemantic = mayaLightParamInfo->parameterSemantic(paramName); MIntArray intValues; MFloatArray floatValues; switch (paramType) { case MHWRender::MLightParameterInformation::kBoolean: case MHWRender::MLightParameterInformation::kInteger: mayaLightParamInfo->getParameter(paramName, intValues); break; case MHWRender::MLightParameterInformation::kFloat: case MHWRender::MLightParameterInformation::kFloat2: case MHWRender::MLightParameterInformation::kFloat3: case MHWRender::MLightParameterInformation::kFloat4: mayaLightParamInfo->getParameter(paramName, floatValues); break; default: // Unsupported paramType. continue; break; } switch (paramSemantic) { case MHWRender::MLightParameterInformation::kLightEnabled: _GetLightingParam(intValues, floatValues, lightEnabled); break; case MHWRender::MLightParameterInformation::kWorldPosition: if (_GetLightingParam(intValues, floatValues, lightPosition)) { lightHasPosition = true; } break; case MHWRender::MLightParameterInformation::kWorldDirection: if (_GetLightingParam(intValues, floatValues, lightDirection)) { lightHasDirection = true; } break; case MHWRender::MLightParameterInformation::kIntensity: _GetLightingParam(intValues, floatValues, lightIntensity); break; case MHWRender::MLightParameterInformation::kColor: _GetLightingParam(intValues, floatValues, lightColor); break; case MHWRender::MLightParameterInformation::kEmitsDiffuse: _GetLightingParam(intValues, floatValues, lightEmitsDiffuse); break; case MHWRender::MLightParameterInformation::kEmitsSpecular: _GetLightingParam(intValues, floatValues, lightEmitsSpecular); break; case MHWRender::MLightParameterInformation::kDecayRate: _GetLightingParam(intValues, floatValues, lightDecayRate); break; case MHWRender::MLightParameterInformation::kDropoff: _GetLightingParam(intValues, floatValues, lightDropoff); break; case MHWRender::MLightParameterInformation::kCosConeAngle: _GetLightingParam(intValues, floatValues, lightCosineConeAngle); break; case MHWRender::MLightParameterInformation::kShadowBias: _GetLightingParam(intValues, floatValues, lightShadowBias); break; case MHWRender::MLightParameterInformation::kShadowOn: _GetLightingParam(intValues, floatValues, lightShadowOn); break; case MHWRender::MLightParameterInformation::kGlobalShadowOn: _GetLightingParam(intValues, floatValues, globalShadowOn); break; default: // Unsupported paramSemantic. continue; break; } if (!lightEnabled) { // Stop reading light parameters if the light is disabled. break; } } if (!lightEnabled) { // Skip to the next light if this light is disabled. continue; } lightColor[0] *= lightIntensity; lightColor[1] *= lightIntensity; lightColor[2] *= lightIntensity; // Populate a GlfSimpleLight from the light information from Maya. GlfSimpleLight light; GfVec4f lightAmbient = blackColor; GfVec4f lightDiffuse = blackColor; GfVec4f lightSpecular = blackColor; // We receive the cone angle from Maya as a pair of floats which // includes the penumbra, but GlfSimpleLights don't currently support // that, so we only use the primary cone angle value. float lightCutoff = GfRadiansToDegrees(std::acos(lightCosineConeAngle[0])); float lightFalloff = lightDropoff; // decayRate is actually an enum in Maya that we receive as a float: // - 0.0 = no attenuation // - 1.0 = linear attenuation // - 2.0 = quadratic attenuation // - 3.0 = cubic attenuation (not supported by GlfSimpleLight) GfVec3f lightAttenuation(0.0f); if (lightDecayRate > 1.5) { // Quadratic attenuation. lightAttenuation[2] = 1.0f; } else if (lightDecayRate > 0.5f) { // Linear attenuation. lightAttenuation[1] = 1.0f; } else { // No/constant attenuation. lightAttenuation[0] = 1.0f; } if (lightHasDirection && !lightHasPosition) { // This is a directional light. Set the direction as its position. lightPosition[0] = -lightDirection[0]; lightPosition[1] = -lightDirection[1]; lightPosition[2] = -lightDirection[2]; lightPosition[3] = 0.0f; // Revert direction to the default value. lightDirection = GfVec3f(0.0f, 0.0f, -1.0f); if (!viewDirectionAlongNegZ) { lightDirection[2] = 1.0f; } } if (!lightHasPosition && !lightHasDirection) { // This is an ambient light. lightAmbient = lightColor; } else { if (lightEmitsDiffuse) { lightDiffuse = lightColor; } if (lightEmitsSpecular) { // XXX: It seems that the specular color cannot be specified // separately from the diffuse color on Maya lights. lightSpecular = lightColor; } } light.SetAmbient(lightAmbient); light.SetDiffuse(lightDiffuse); light.SetSpecular(lightSpecular); light.SetPosition(lightPosition); light.SetSpotDirection(lightDirection); light.SetSpotCutoff(lightCutoff); light.SetSpotFalloff(lightFalloff); light.SetAttenuation(lightAttenuation); light.SetShadowBias(lightShadowBias); light.SetHasShadow(lightShadowOn && globalShadowOn); lights.push_back(light); } lightingContext->SetLights(lights); // XXX: These material settings match what we used to get when we read the // material from OpenGL. This should probably eventually be something more // sophisticated. GlfSimpleMaterial material; material.SetAmbient(whiteColor); material.SetDiffuse(whiteColor); material.SetSpecular(blackColor); material.SetEmission(blackColor); material.SetShininess(0.0001f); lightingContext->SetMaterial(material); lightingContext->SetSceneAmbient(blackColor); return lightingContext; }