1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #include "pxr/usd/usdRender/spec.h"
25 #include "pxr/usd/usdRender/settings.h"
26 #include "pxr/usd/usdRender/product.h"
27 #include "pxr/usd/usdRender/var.h"
28 #include "pxr/usd/usdGeom/camera.h"
29 #include "pxr/base/gf/camera.h"
30 #include "pxr/base/gf/frustum.h"
31 
32 PXR_NAMESPACE_OPEN_SCOPE
33 
34 static void
_ReadExtraSettings(UsdPrim const & prim,VtDictionary * extraSettings,std::vector<std::string> const & namespaces)35 _ReadExtraSettings(UsdPrim const& prim, VtDictionary *extraSettings,
36                    std::vector<std::string> const& namespaces)
37 {
38     std::vector<UsdAttribute> attrs = prim.GetAuthoredAttributes();
39     for (UsdAttribute attr: attrs) {
40         if (namespaces.empty()) {
41             if (attr.HasFallbackValue()) {
42                 // Skip attributes built into schemas.
43                 continue;
44             }
45         } else {
46             bool attrIsInRequestedNS = false;
47             for (std::string const& ns: namespaces) {
48                 if (TfStringStartsWith(attr.GetName(), ns)) {
49                     attrIsInRequestedNS = true;
50                     break;
51                 }
52             }
53             if (!attrIsInRequestedNS) {
54                 continue;
55             }
56         }
57         VtValue val;
58         if (attr.Get(&val)) {
59             (*extraSettings)[attr.GetName()] = val;
60         }
61     }
62 }
63 
64 template<typename T>
65 inline bool
_Get(UsdAttribute const & attr,T * val,bool sparse=false)66 _Get(UsdAttribute const &attr, T* val, bool sparse=false)
67 {
68     if (!sparse || attr.HasAuthoredValue()) {
69         return attr.Get(val);
70     }
71     return false;
72 }
73 
74 static void
_ReadSettingsBase(UsdRenderSettingsBase const & base,UsdRenderSpec::Product * pd,bool sparse)75 _ReadSettingsBase(UsdRenderSettingsBase const& base,
76                   UsdRenderSpec::Product *pd,
77                   bool sparse)
78 {
79     SdfPathVector targets;
80     base.GetCameraRel().GetForwardedTargets(&targets);
81     if (!targets.empty()) {
82         pd->cameraPath = targets[0];
83     }
84     _Get( base.GetResolutionAttr(), &pd->resolution, sparse );
85     _Get( base.GetPixelAspectRatioAttr(), &pd->pixelAspectRatio, sparse );
86     _Get( base.GetAspectRatioConformPolicyAttr(),
87           &pd->aspectRatioConformPolicy, sparse );
88     {
89         // Convert dataWindowNDC from vec4 to range2.
90         GfVec4f dataWindowNDCVec;
91         if (_Get( base.GetDataWindowNDCAttr(), &dataWindowNDCVec, sparse )) {
92             pd->dataWindowNDC = GfRange2f(
93                 GfVec2f(dataWindowNDCVec[0], dataWindowNDCVec[1]),
94                 GfVec2f(dataWindowNDCVec[2], dataWindowNDCVec[3]));
95         }
96     }
97     _Get( base.GetInstantaneousShutterAttr(),
98           &pd->instantaneousShutter, sparse );
99 }
100 
101 // TODO: Consolidate with CameraUtilConformedWindow().  Resolve policy
102 // name mismatches; also CameraUtil cannot compensate pixelAspectRatio.
_ApplyAspectRatioPolicy(UsdRenderSpec::Product * product)103 static void _ApplyAspectRatioPolicy(
104     UsdRenderSpec::Product *product)
105 {
106     // Gather dimensions
107     GfVec2i res = product->resolution;
108     GfVec2f size = product->apertureSize;
109     // Validate dimensions
110     if (res[0] <= 0.0 || res[1] <= 0.0 || size[0] <= 0.0 || size[1] <= 0.0) {
111         return;
112     }
113     // Compute aspect ratios
114     float resAspectRatio = float(res[0]) / float(res[1]);
115     float imageAspectRatio = product->pixelAspectRatio * resAspectRatio;
116     if (imageAspectRatio <= 0.0) {
117         return;
118     }
119     float apertureAspectRatio = size[0] / size[1];
120     // Apply policy
121     TfToken const& policy = product->aspectRatioConformPolicy;
122     enum { Width, Height, None } adjust = None;
123     if (policy == UsdRenderTokens->adjustPixelAspectRatio) {
124         product->pixelAspectRatio = apertureAspectRatio / resAspectRatio;
125     } else if (policy == UsdRenderTokens->adjustApertureHeight) {
126         adjust = Height;
127     } else if (policy == UsdRenderTokens->adjustApertureWidth) {
128         adjust = Width;
129     } else if (policy == UsdRenderTokens->expandAperture) {
130         adjust = (apertureAspectRatio > imageAspectRatio) ? Height : Width;
131     } else if (policy == UsdRenderTokens->cropAperture) {
132         adjust = (apertureAspectRatio > imageAspectRatio) ? Width : Height;
133     }
134     // Adjust aperture so that size[0] / size[1] == imageAspectRatio.
135     if (adjust == Width) {
136         product->apertureSize[0] = size[1] * imageAspectRatio;
137     } else if (adjust == Height) {
138         product->apertureSize[1] = size[0] / imageAspectRatio;
139     }
140 }
141 
142 UsdRenderSpec
UsdRenderComputeSpec(UsdRenderSettings const & settings,UsdTimeCode time,std::vector<std::string> const & extraNamespaces)143 UsdRenderComputeSpec(
144     UsdRenderSettings const& settings,
145     UsdTimeCode time,
146     std::vector<std::string> const& extraNamespaces)
147 {
148     UsdRenderSpec rd;
149     UsdPrim prim = settings.GetPrim();
150     UsdStageWeakPtr stage = prim.GetStage();
151     if (!stage) {
152         TF_CODING_ERROR("Invalid stage\n");
153         return rd;
154     }
155 
156     // Read shared settings as a "base product".
157     UsdRenderSpec::Product base;
158     _ReadSettingsBase(UsdRenderSettingsBase(prim), &base, false);
159     _ReadExtraSettings(prim, &base.extraSettings, extraNamespaces);
160 
161     // Products
162     SdfPathVector targets;
163     settings.GetProductsRel().GetForwardedTargets(&targets);
164     for (SdfPath const& target: targets) {
165         if (UsdRenderProduct product =
166             UsdRenderProduct(stage->GetPrimAtPath(target))) {
167             UsdRenderSpec::Product pd = base;
168 
169             // Read product-specific overrides to base render settings.
170             _ReadSettingsBase(UsdRenderSettingsBase(product), &pd, true);
171 
172             // Read camera aperture and apply aspectRatioConformPolicy.
173             if (UsdGeomCamera cam =
174                 UsdGeomCamera(stage->GetPrimAtPath(pd.cameraPath))) {
175                 cam.GetHorizontalApertureAttr().Get(&pd.apertureSize[0]);
176                 cam.GetVerticalApertureAttr().Get(&pd.apertureSize[1]);
177                 _ApplyAspectRatioPolicy(&pd);
178             } else {
179                 TF_RUNTIME_ERROR("UsdRenderSettings: Could not find camera "
180                                  "<%s> for product <%s>\n",
181                                  pd.cameraPath.GetText(), target.GetText());
182                 continue;
183             }
184 
185             // Read product-only settings.
186             product.GetProductTypeAttr().Get(&pd.type);
187             product.GetProductNameAttr().Get(&pd.name);
188 
189             // Read render vars.
190             SdfPathVector renderVarPaths;
191             product.GetOrderedVarsRel().GetForwardedTargets(&renderVarPaths);
192             for (SdfPath const& renderVarPath: renderVarPaths ) {
193                 bool foundExisting = false;
194                 for (size_t i=0; i < rd.renderVars.size(); ++i) {
195                     if (rd.renderVars[i].renderVarPath == renderVarPath) {
196                         pd.renderVarIndices.push_back(i);
197                         foundExisting = true;
198                         break;
199                     }
200                 }
201                 if (!foundExisting) {
202                     UsdPrim prim = stage->GetPrimAtPath(renderVarPath);
203                     if (prim.IsA<UsdRenderVar>()) {
204                         UsdRenderVar rv(prim);
205                         UsdRenderSpec::RenderVar rvd;
206                         // Store schema-defined attributes in explicit fields.
207                         rvd.renderVarPath = renderVarPath;
208                         rv.GetDataTypeAttr().Get(&rvd.dataType);
209                         rv.GetSourceNameAttr().Get(&rvd.sourceName);
210                         rv.GetSourceTypeAttr().Get(&rvd.sourceType);
211                         // Store any other custom attributes in extraSettings.
212                         _ReadExtraSettings(prim, &rvd.extraSettings,
213                                            extraNamespaces);
214                         // Record new render var.
215                         pd.renderVarIndices.push_back(rd.renderVars.size());
216                         rd.renderVars.emplace_back(rvd);
217                     } else {
218                         TF_RUNTIME_ERROR("Render product <%s> includes "
219                                          "render var at path <%s>, but "
220                                          "no suitable UsdRenderVar prim "
221                                          "was found.  Skipping.",
222                                          target.GetText(),
223                                          renderVarPath.GetText());
224                     }
225                 }
226             }
227             // Store any other custom attributes in extraSettings.
228             _ReadExtraSettings(product.GetPrim(), &pd.extraSettings,
229                                extraNamespaces);
230             rd.products.emplace_back(pd);
231         }
232     }
233 
234     // Scene configuration
235     settings.GetMaterialBindingPurposesAttr().Get(&rd.materialBindingPurposes);
236     settings.GetIncludedPurposesAttr().Get(&rd.includedPurposes);
237     // Store any other custom attributes in extraSettings.
238     _ReadExtraSettings(prim, &rd.extraSettings, extraNamespaces);
239 
240     return rd;
241 }
242 
243 PXR_NAMESPACE_CLOSE_SCOPE
244