/* 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 PxrUsdKatanaReadPointInstancer( const UsdGeomPointInstancer& instancer, const PxrUsdKatanaUsdInPrivateData& data, PxrUsdKatanaAttrMap& instancerAttrMap, PxrUsdKatanaAttrMap& sourcesAttrMap, PxrUsdKatanaAttrMap& instancesAttrMap, PxrUsdKatanaAttrMap& inputAttrMap) { const double currentTime = data.GetCurrentTime(); PxrUsdKatanaReadXformable(instancer, data, instancerAttrMap); // Get primvars for setting later. Unfortunatley, the only way to get them // out of the attr map is to build it, which will cause its contents to be // cleared. We'll need to restore its contents before continuing. // FnKat::GroupAttribute instancerAttrs = instancerAttrMap.build(); FnKat::GroupAttribute primvarAttrs = instancerAttrs.getChildByName("geometry.arbitrary"); for (int64_t i = 0; i < instancerAttrs.getNumberOfChildren(); ++i) { instancerAttrMap.set(instancerAttrs.getChildName(i), instancerAttrs.getChildByIndex(i)); } instancerAttrMap.set("type", FnKat::StringAttribute("usd point instancer")); const std::string fileName = data.GetUsdInArgs()->GetFileName(); instancerAttrMap.set("info.usd.fileName", FnKat::StringAttribute(fileName)); FnKat::GroupAttribute inputAttrs = inputAttrMap.build(); const std::string katOutputPath = FnKat::StringAttribute( inputAttrs.getChildByName("outputLocationPath")).getValue("", false); if (katOutputPath.empty()) { _LogAndSetError(instancerAttrMap, "No output location path specified"); return; } // // Validate instancer data. // const std::string instancerPath = instancer.GetPath().GetString(); UsdStageWeakPtr stage = instancer.GetPrim().GetStage(); // Prototypes (required) // SdfPathVector protoPaths; instancer.GetPrototypesRel().GetTargets(&protoPaths); if (protoPaths.empty()) { _LogAndSetError(instancerAttrMap, "Instancer has no prototypes"); return; } _PathToPrimMap primCache; for (auto protoPath : protoPaths) { const UsdPrim &protoPrim = stage->GetPrimAtPath(protoPath); primCache[protoPath] = protoPrim; } // Indices (required) // VtIntArray protoIndices; if (!instancer.GetProtoIndicesAttr().Get(&protoIndices, currentTime)) { _LogAndSetError(instancerAttrMap, "Instancer has no prototype indices"); return; } const size_t numInstances = protoIndices.size(); if (numInstances == 0) { _LogAndSetError(instancerAttrMap, "Instancer has no prototype indices"); return; } for (auto protoIndex : protoIndices) { if (protoIndex < 0 || static_cast<size_t>(protoIndex) >= protoPaths.size()) { _LogAndSetError(instancerAttrMap, TfStringPrintf( "Out of range prototype index %d", protoIndex)); return; } } // Mask (optional) // std::vector<bool> pruneMaskValues = instancer.ComputeMaskAtTime(currentTime); if (!pruneMaskValues.empty() and pruneMaskValues.size() != numInstances) { _LogAndSetError(instancerAttrMap, "Mismatch in length of indices and mask"); return; } // Positions (required) // UsdAttribute positionsAttr = instancer.GetPositionsAttr(); if (!positionsAttr.HasValue()) { _LogAndSetError(instancerAttrMap, "Instancer has no positions"); return; } // // Compute instance transform matrices. // const double timeCodesPerSecond = stage->GetTimeCodesPerSecond(); // Gather frame-relative sample times and add them to the current time to // generate absolute sample times. // const std::vector<double> &motionSampleTimes = data.GetMotionSampleTimes(positionsAttr); const size_t sampleCount = motionSampleTimes.size(); std::vector<UsdTimeCode> sampleTimes(sampleCount); for (size_t a = 0; a < sampleCount; ++a) { sampleTimes[a] = UsdTimeCode(currentTime + motionSampleTimes[a]); } // Get velocityScale from the opArgs. // float velocityScale = FnKat::FloatAttribute( inputAttrs.getChildByName("opArgs.velocityScale")).getValue(1.0f, false); // XXX Replace with UsdGeomPointInstancer::ComputeInstanceTransformsAtTime. // std::vector<std::vector<GfMatrix4d>> xformSamples(sampleCount); const size_t numXformSamples = _ComputeInstanceTransformsAtTime(xformSamples, instancer, sampleTimes, UsdTimeCode(currentTime), timeCodesPerSecond, numInstances, positionsAttr, velocityScale); if (numXformSamples == 0) { _LogAndSetError(instancerAttrMap, "Could not compute " "sample/topology-invarying instance " "transform matrix"); return; } // // Compute prototype bounds. // bool aggregateBoundsValid = false; std::vector<double> aggregateBounds; // XXX Replace with UsdGeomPointInstancer::ComputeExtentAtTime. // VtVec3fArray aggregateExtent; if (_ComputeExtentAtTime( aggregateExtent, data.GetUsdInArgs(), xformSamples, motionSampleTimes, protoIndices, protoPaths, primCache, pruneMaskValues)) { aggregateBoundsValid = true; aggregateBounds.resize(6); aggregateBounds[0] = aggregateExtent[0][0]; // min x aggregateBounds[1] = aggregateExtent[1][0]; // max x aggregateBounds[2] = aggregateExtent[0][1]; // min y aggregateBounds[3] = aggregateExtent[1][1]; // max y aggregateBounds[4] = aggregateExtent[0][2]; // min z aggregateBounds[5] = aggregateExtent[1][2]; // max z } // // Build sources. Keep track of which instances use them. // FnGeolibServices::StaticSceneCreateOpArgsBuilder sourcesBldr(false); std::vector<int> instanceIndices; instanceIndices.reserve(numInstances); std::vector<std::string> instanceSources; instanceSources.reserve(protoPaths.size()); std::map<std::string, int> instanceSourceIndexMap; std::vector<int> omitList; omitList.reserve(numInstances); std::map<SdfPath, std::string> protoPathsToKatPaths; for (size_t i = 0; i < numInstances; ++i) { int index = protoIndices[i]; // Check to see if we are pruned. // bool isPruned = (!pruneMaskValues.empty() and pruneMaskValues[i] == false); if (isPruned) { omitList.push_back(i); } const SdfPath &protoPath = protoPaths[index]; // Compute the full (Katana) path to this prototype. // std::string fullProtoPath; std::map<SdfPath, std::string>::const_iterator pptkpIt = protoPathsToKatPaths.find(protoPath); if (pptkpIt != protoPathsToKatPaths.end()) { fullProtoPath = pptkpIt->second; } else { _PathToPrimMap::const_iterator pcIt = primCache.find(protoPath); const UsdPrim &protoPrim = pcIt->second; if (!protoPrim) { continue; } // Determine where (what path) to start building the prototype prim // such that its material bindings will be preserved. This could be // the prototype path itself or an ancestor path. // SdfPathVector commonPrefixes; UsdRelationship materialBindingsRel = UsdShadeMaterial::GetBindingRel(protoPrim); auto assetAPI = UsdModelAPI(protoPrim); std::string assetName; bool isReferencedModelPrim = assetAPI.IsModel() and assetAPI.GetAssetName(&assetName); if (!materialBindingsRel or isReferencedModelPrim) { // The prim has no material bindings or is a referenced model // prim (meaning that materials are defined below it); start // building at the prototype path. // commonPrefixes.push_back(protoPath); } else { SdfPathVector materialPaths; materialBindingsRel.GetForwardedTargets(&materialPaths); for (auto materialPath : materialPaths) { const SdfPath &commonPrefix = protoPath.GetCommonPrefix(materialPath); if (commonPrefix.GetString() == "/") { // XXX Unhandled case. // The prototype prim and its material are not under the // same parent; start building at the prototype path // (although it is likely that bindings will be broken). // commonPrefixes.push_back(protoPath); } else { // Start building at the common ancestor between the // prototype prim and its material. // commonPrefixes.push_back(commonPrefix); } } } // XXX Unhandled case. // We'll use the first common ancestor even if there is more than // one (which shouldn't appen if the prototype prim and its bindings // are under the same parent). // SdfPath::RemoveDescendentPaths(&commonPrefixes); const std::string buildPath = commonPrefixes[0].GetString(); // See if the path is a child of the point instancer. If so, we'll // match its hierarchy. If not, we'll put it under a 'prototypes' // group. // std::string relBuildPath; if (pystring::startswith(buildPath, instancerPath + "/")) { relBuildPath = pystring::replace( buildPath, instancerPath + "/", ""); } else { relBuildPath = "prototypes/" + FnGeolibUtil::Path::GetLeafName(buildPath); } // Start generating the full path to the prototype. // fullProtoPath = katOutputPath + "/" + relBuildPath; // Make the common ancestor our instance source. // sourcesBldr.setAttrAtLocation(relBuildPath, "type", FnKat::StringAttribute("instance source")); // Author a tracking attr. // sourcesBldr.setAttrAtLocation(relBuildPath, "info.usd.sourceUsdPath", FnKat::StringAttribute(buildPath)); // Tell the BuildIntermediate op to start building at the common // ancestor. // sourcesBldr.setAttrAtLocation(relBuildPath, "usdPrimPath", FnKat::StringAttribute(buildPath)); sourcesBldr.setAttrAtLocation(relBuildPath, "usdPrimName", FnKat::StringAttribute("geo")); if (protoPath.GetString() != buildPath) { // Finish generating the full path to the prototype. // fullProtoPath = fullProtoPath + "/geo" + pystring::replace( protoPath.GetString(), buildPath, ""); } // Create a mapping that will link the instance's index to its // prototype's full path. // instanceSourceIndexMap[fullProtoPath] = instanceSources.size(); instanceSources.push_back(fullProtoPath); // Finally, store the full path in the map so we won't have to do // this work again. // protoPathsToKatPaths[protoPath] = fullProtoPath; } instanceIndices.push_back(instanceSourceIndexMap[fullProtoPath]); } // // Build instances. // FnGeolibServices::StaticSceneCreateOpArgsBuilder instancesBldr(false); instancesBldr.createEmptyLocation("instances", "instance array"); instancesBldr.setAttrAtLocation("instances", "geometry.instanceSource", FnKat::StringAttribute(instanceSources, 1)); instancesBldr.setAttrAtLocation("instances", "geometry.instanceIndex", FnKat::IntAttribute(&instanceIndices[0], instanceIndices.size(), 1)); FnKat::DoubleBuilder instanceMatrixBldr(16); for (size_t a = 0; a < numXformSamples; ++a) { double relSampleTime = motionSampleTimes[a]; // Shove samples into the builder at the frame-relative sample time. If // motion is backwards, make sure to reverse time samples. std::vector<double> &matVec = instanceMatrixBldr.get( data.IsMotionBackward() ? PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); matVec.reserve(16 * numInstances); for (size_t i = 0; i < numInstances; ++i) { GfMatrix4d instanceXform = xformSamples[a][i]; const double *matArray = instanceXform.GetArray(); for (int j = 0; j < 16; ++j) { matVec.push_back(matArray[j]); } } } instancesBldr.setAttrAtLocation("instances", "geometry.instanceMatrix", instanceMatrixBldr.build()); if (!omitList.empty()) { instancesBldr.setAttrAtLocation("instances", "geometry.omitList", FnKat::IntAttribute(&omitList[0], omitList.size(), 1)); } instancesBldr.setAttrAtLocation("instances", "geometry.pointInstancerId", FnKat::StringAttribute(katOutputPath)); // // Transfer primvars. // FnKat::GroupBuilder instancerPrimvarsBldr; FnKat::GroupBuilder instancesPrimvarsBldr; for (int64_t i = 0; i < primvarAttrs.getNumberOfChildren(); ++i) { const std::string primvarName = primvarAttrs.getChildName(i); // Use "point" scope for the instancer. instancerPrimvarsBldr.set(primvarName, primvarAttrs.getChildByIndex(i)); instancerPrimvarsBldr.set(primvarName + ".scope", FnKat::StringAttribute("point")); // User "primitive" scope for the instances. instancesPrimvarsBldr.set(primvarName, primvarAttrs.getChildByIndex(i)); instancesPrimvarsBldr.set(primvarName + ".scope", FnKat::StringAttribute("primitive")); } instancerAttrMap.set("geometry.arbitrary", instancerPrimvarsBldr.build()); instancesBldr.setAttrAtLocation("instances", "geometry.arbitrary", instancesPrimvarsBldr.build()); // // Set the final aggregate bounds. // if (aggregateBoundsValid) { instancerAttrMap.set("bound", FnKat::DoubleAttribute(&aggregateBounds[0], 6, 2)); } // // Set proxy attrs. // instancerAttrMap.set("proxies", PxrUsdKatanaUtils::GetViewerProxyAttr(data)); // // Transfer builder results to our attr maps. // FnKat::GroupAttribute sourcesAttrs = sourcesBldr.build(); for (int64_t i = 0; i < sourcesAttrs.getNumberOfChildren(); ++i) { sourcesAttrMap.set( sourcesAttrs.getChildName(i), sourcesAttrs.getChildByIndex(i)); } FnKat::GroupAttribute instancesAttrs = instancesBldr.build(); for (int64_t i = 0; i < instancesAttrs.getNumberOfChildren(); ++i) { instancesAttrMap.set( instancesAttrs.getChildName(i), instancesAttrs.getChildByIndex(i)); } }
void GlfSimpleLightingContext::SetStateFromOpenGL() { // import classic GL light's parameters into shaded lights SetUseLighting(glIsEnabled(GL_LIGHTING)); GfMatrix4d worldToViewMatrix; glGetDoublev(GL_MODELVIEW_MATRIX, worldToViewMatrix.GetArray()); GfMatrix4d viewToWorldMatrix = worldToViewMatrix.GetInverse(); GLint nLights = 0; glGetIntegerv(GL_MAX_LIGHTS, &nLights); GlfSimpleLightVector lights; lights.reserve(nLights); GlfSimpleLight light; for(int i = 0; i < nLights; ++i) { int lightName = GL_LIGHT0 + i; if (glIsEnabled(lightName)) { GLfloat position[4], color[4]; glGetLightfv(lightName, GL_POSITION, position); light.SetPosition(GfVec4f(position)*viewToWorldMatrix); glGetLightfv(lightName, GL_AMBIENT, color); light.SetAmbient(GfVec4f(color)); glGetLightfv(lightName, GL_DIFFUSE, color); light.SetDiffuse(GfVec4f(color)); glGetLightfv(lightName, GL_SPECULAR, color); light.SetSpecular(GfVec4f(color)); lights.push_back(light); } } SetLights(lights); GlfSimpleMaterial material; GLfloat color[4], shininess; glGetMaterialfv(GL_FRONT, GL_AMBIENT, color); material.SetAmbient(GfVec4f(color)); glGetMaterialfv(GL_FRONT, GL_DIFFUSE, color); material.SetDiffuse(GfVec4f(color)); glGetMaterialfv(GL_FRONT, GL_SPECULAR, color); material.SetSpecular(GfVec4f(color)); glGetMaterialfv(GL_FRONT, GL_EMISSION, color); material.SetEmission(GfVec4f(color)); glGetMaterialfv(GL_FRONT, GL_SHININESS, &shininess); // clamp to 0.0001, since pow(0,0) is undefined in GLSL. shininess = std::max(0.0001f, shininess); material.SetShininess(shininess); SetMaterial(material); GfVec4f sceneAmbient; glGetFloatv(GL_LIGHT_MODEL_AMBIENT, &sceneAmbient[0]); SetSceneAmbient(sceneAmbient); }