@@ -1202,6 +1202,95 @@ importFbxPatch(ImportFbxContext& ctx, FbxNodeAttribute* attribute, int parent)
12021202bool
12031203importFbxLight (ImportFbxContext& ctx, FbxNodeAttribute* attribute, int parent)
12041204{
1205+ FbxLight* fbxLight = FbxCast<FbxLight>(attribute);
1206+ if (!fbxLight) {
1207+ // FbxCast is safe, so if it fails, it returns a null pointer. If that happens, that means
1208+ // the attribute is not a light, even though this function should only be called on
1209+ // attributes with GetAttributeType() == FbxNodeAttribute::eLight
1210+ TF_WARN (" importFbxLight: Non-light FBX node attribute cannot be processed as a light." );
1211+ return false ;
1212+ }
1213+
1214+ std::string type;
1215+ LightType usdType;
1216+ float coneAngle = 0 ;
1217+ float coneFalloff = 0 ;
1218+ switch (fbxLight->LightType .Get ()) {
1219+ case FbxLight::ePoint:
1220+ type = " sphere (from FBX point light)" ;
1221+ usdType = LightType::Sphere;
1222+
1223+ break ;
1224+ case FbxLight::eDirectional:
1225+ type = " sun (from FBX directional light)" ;
1226+ usdType = LightType::Sun;
1227+
1228+ break ;
1229+ case FbxLight::eSpot:
1230+ type = " disk (from FBX spot light)" ;
1231+ usdType = LightType::Disk;
1232+
1233+ // According to FBX specs, inner angle is "HotSpot". In USD, this translates to the
1234+ // USDLuxShapingAPI ConeAngleAttribute
1235+ coneAngle = fbxLight->InnerAngle .Get ();
1236+ // According to FBX specs, outer angle is falloff. In USD, this translates to the
1237+ // USDLuxShapingAPI ConeSoftnessAttribute
1238+ coneFalloff = fbxLight->OuterAngle .Get ();
1239+
1240+ break ;
1241+ case FbxLight::eArea:
1242+ TF_WARN (" importFbxLight: ignoring unsupported light of type \" area\"\n " );
1243+
1244+ return false ;
1245+ case FbxLight::eVolume:
1246+ TF_WARN (" importFbxLight: ignoring unsupported light of type \" volume\"\n " );
1247+
1248+ return false ;
1249+ default :
1250+ TF_WARN (" importFbxLight: ignoring light of unknown type\n " );
1251+
1252+ return false ;
1253+ }
1254+
1255+ auto [lightIndex, light] = ctx.usd ->addLight ();
1256+ auto [nodeIndex, node] = ctx.usd ->getParent (parent);
1257+ node.light = lightIndex;
1258+
1259+ light.type = usdType;
1260+ light.coneAngle = coneAngle;
1261+ light.coneFalloff = coneFalloff;
1262+
1263+ light.name = fbxLight->GetName ();
1264+ light.color = toVec3f (fbxLight->Color .Get ());
1265+ light.intensity = fbxLight->Intensity .Get () * FBX_TO_USD_INTENSITY_SCALE_FACTOR;
1266+
1267+ // From testing, this appears to ensure FBX lights are properly oriented once imported
1268+ // TODO: Investigate why this is necessary
1269+ GfRotation rotationOffset = GfRotation (GfVec3d::XAxis (), -90.0 );
1270+
1271+ auto reorientCamera = [rotationOffset](const GfQuatf rotation) {
1272+ return GfQuatf ((rotationOffset * GfRotation (rotation)).GetQuat ());
1273+ };
1274+
1275+ // Reorient the light's rotation. Usually, light animations are done by animating the
1276+ // parent of the light, but in case the light itself is animated, update those rotations
1277+ // as well
1278+ node.rotation = reorientCamera (node.rotation );
1279+ for (size_t rotationIdx = 0 ; rotationIdx < node.rotations .values .size (); ++rotationIdx) {
1280+ node.rotations .values [rotationIdx] = reorientCamera (node.rotations .values [rotationIdx]);
1281+ }
1282+
1283+ TF_DEBUG_MSG (FILE_FORMAT_FBX,
1284+ " importFbx: light[%d]{ %s } of type %s\n " ,
1285+ lightIndex,
1286+ light.name .c_str (),
1287+ type.c_str ());
1288+
1289+ // TODO: Extract FBX light radius and replace this temporary dummy value with it. When this is
1290+ // updated, please update corresponding unit tests as well
1291+ light.radius = 0.5 ;
1292+ TF_WARN (" importFbxLight: ignoring FBX light radius, setting radius=0.5\n " );
1293+
12051294 return true ;
12061295}
12071296bool
@@ -1216,6 +1305,13 @@ importFbxCamera(ImportFbxContext& ctx, FbxNodeAttribute* attribute, int parent)
12161305{
12171306 std::string name = " " ;
12181307 FbxCamera* fbxCamera = FbxCast<FbxCamera>(attribute);
1308+ if (!fbxCamera) {
1309+ // FbxCast is safe, so if it fails, it returns a null pointer. If that happens, that means
1310+ // the attribute is not a camera, even though this function should only be called on
1311+ // attributes with GetAttributeType() == FbxNodeAttribute::eCamera
1312+ TF_WARN (" importFbxCamera: Non-camera FBX node attribute cannot be processed as a camera." );
1313+ return false ;
1314+ }
12191315 auto [cameraIndex, camera] = ctx.usd ->addCamera ();
12201316 auto [nodeIndex, node] = ctx.usd ->getParent (parent);
12211317 node.camera = cameraIndex;
0 commit comments