1 //-*****************************************************************************
2 //
3 // Copyright (c) 2009-2012,
4 // Sony Pictures Imageworks Inc. and
5 // Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
6 //
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are
11 // met:
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above
15 // copyright notice, this list of conditions and the following disclaimer
16 // in the documentation and/or other materials provided with the
17 // distribution.
18 // * Neither the name of Sony Pictures Imageworks, nor
19 // Industrial Light & Magic, nor the names of their contributors may be used
20 // to endorse or promote products derived from this software without specific
21 // prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 //
35 //-*****************************************************************************
36
37 #include "MayaCameraWriter.h"
38
MayaCameraWriter(MDagPath & iDag,Alembic::Abc::OObject & iParent,Alembic::Util::uint32_t iTimeIndex,const JobArgs & iArgs)39 MayaCameraWriter::MayaCameraWriter(MDagPath & iDag,
40 Alembic::Abc::OObject & iParent, Alembic::Util::uint32_t iTimeIndex,
41 const JobArgs & iArgs) :
42 mIsAnimated(false),
43 mDagPath(iDag),
44 mUseRenderShutter(false),
45 mShutterOpen(0.0),
46 mShutterClose(0.0)
47 {
48 MStatus status = MS::kSuccess;
49 MFnCamera cam(iDag, &status);
50 if (!status)
51 {
52 MGlobal::displayError( "MFnCamera() failed for MayaCameraWriter" );
53 }
54
55 MString name = cam.name();
56 name = util::stripNamespaces(name, iArgs.stripNamespace);
57
58 Alembic::AbcGeom::OCamera obj(iParent, name.asChar(), iTimeIndex);
59 mSchema = obj.getSchema();
60
61 MObject cameraObj = iDag.node();
62 if (iTimeIndex != 0 && util::isAnimated(cameraObj))
63 {
64 mIsAnimated = true;
65 }
66 else
67 {
68 iTimeIndex = 0;
69 }
70
71 MObject renderObj;
72 MSelectionList sel;
73 sel.add("defaultRenderGlobals");
74
75 if (!sel.isEmpty())
76 {
77 sel.getDependNode(0, renderObj);
78 MFnDependencyNode dep(renderObj);
79 MPlug plug = dep.findPlug("motionBlurUseShutter", true);
80 if (plug.asBool())
81 {
82 MTime sec(1.0, MTime::kSeconds);
83 double val = sec.as(MTime::uiUnit());
84
85 mUseRenderShutter = true;
86 plug = dep.findPlug("motionBlurShutterOpen", true);
87 mShutterOpen = plug.asDouble() / val;
88 plug = dep.findPlug("motionBlurShutterClose", true);
89 mShutterClose = plug.asDouble() / val;
90 }
91 }
92
93 Alembic::Abc::OCompoundProperty cp;
94 Alembic::Abc::OCompoundProperty up;
95 if (AttributesWriter::hasAnyAttr(cam, iArgs))
96 {
97 cp = mSchema.getArbGeomParams();
98 up = mSchema.getUserProperties();
99 }
100
101 mAttrs = AttributesWriterPtr(new AttributesWriter(cp, up, obj, cam,
102 iTimeIndex, iArgs, true));
103
104 if (!mIsAnimated || iArgs.setFirstAnimShape)
105 {
106 write();
107 }
108 }
109
write()110 void MayaCameraWriter::write()
111 {
112 MFnCamera mfnCamera(mDagPath);
113
114 mSamp.setFocalLength(mfnCamera.focalLength());
115 mSamp.setLensSqueezeRatio(mfnCamera.lensSqueezeRatio());
116 mSamp.setHorizontalAperture(mfnCamera.horizontalFilmAperture() * 2.54);
117 mSamp.setVerticalAperture(mfnCamera.verticalFilmAperture() * 2.54);
118 mSamp.setHorizontalFilmOffset(mfnCamera.horizontalFilmOffset() * 2.54);
119 mSamp.setVerticalFilmOffset(mfnCamera.verticalFilmOffset() * 2.54);
120 double overscan = mfnCamera.overscan() - 1.0;
121 mSamp.setOverScanLeft(overscan);
122 mSamp.setOverScanRight(overscan);
123 mSamp.setOverScanTop(overscan);
124 mSamp.setOverScanBottom(overscan);
125 mSamp.setNearClippingPlane(mfnCamera.nearClippingPlane());
126 mSamp.setFarClippingPlane(mfnCamera.farClippingPlane());
127 mSamp.setFStop(mfnCamera.fStop());
128 mSamp.setFocusDistance(mfnCamera.focusDistance());
129
130 // should this be based on the shutterAngle? or the settings passed in?
131
132 if (mUseRenderShutter)
133 {
134 mSamp.setShutterOpen(mShutterOpen);
135 mSamp.setShutterClose(mShutterClose);
136 }
137 else
138 {
139 MTime sec(1.0, MTime::kSeconds);
140 mSamp.setShutterOpen(0.0);
141 mSamp.setShutterClose(
142 Alembic::AbcGeom::RadiansToDegrees(mfnCamera.shutterAngle()) /
143 ( 360.0 * sec.as(MTime::uiUnit()) ));
144 }
145
146 // build up the film fit and post projection matrix
147 if (mSchema.getNumSamples() == 0)
148 {
149 // film fit first
150 std::string filmFitName = "filmFit";
151 mFilmFit = mfnCamera.filmFit();
152 switch (mFilmFit)
153 {
154 case MFnCamera::kFillFilmFit:
155 {
156 Alembic::AbcGeom::FilmBackXformOp fit(
157 Alembic::AbcGeom::kScaleFilmBackOperation, "filmFitFill");
158 mSamp.addOp(fit);
159 }
160 break;
161
162 case MFnCamera::kHorizontalFilmFit:
163 {
164 Alembic::AbcGeom::FilmBackXformOp fit(
165 Alembic::AbcGeom::kScaleFilmBackOperation, "filmFitHorz");
166 mSamp.addOp(fit);
167
168 Alembic::AbcGeom::FilmBackXformOp offset(
169 Alembic::AbcGeom::kTranslateFilmBackOperation,
170 "filmFitOffs");
171 mSamp.addOp(offset);
172 }
173 break;
174
175 case MFnCamera::kVerticalFilmFit:
176 {
177 Alembic::AbcGeom::FilmBackXformOp fit(
178 Alembic::AbcGeom::kScaleFilmBackOperation, "filmFitVert");
179 mSamp.addOp(fit);
180
181 Alembic::AbcGeom::FilmBackXformOp offset(
182 Alembic::AbcGeom::kTranslateFilmBackOperation,
183 "filmFitOffs");
184 mSamp.addOp(offset);
185 }
186 break;
187
188 case MFnCamera::kOverscanFilmFit:
189 {
190 Alembic::AbcGeom::FilmBackXformOp fit(
191 Alembic::AbcGeom::kScaleFilmBackOperation, "filmFitOver");
192 mSamp.addOp(fit);
193 }
194 break;
195
196 default:
197 break;
198 }
199
200 Alembic::AbcGeom::FilmBackXformOp preScale(
201 Alembic::AbcGeom::kScaleFilmBackOperation, "preScale");
202 mSamp.addOp(preScale);
203
204 Alembic::AbcGeom::FilmBackXformOp filmTranslate(
205 Alembic::AbcGeom::kTranslateFilmBackOperation, "filmTranslate");
206 mSamp.addOp(filmTranslate);
207
208 // skip film roll for now
209
210 Alembic::AbcGeom::FilmBackXformOp postScale(
211 Alembic::AbcGeom::kScaleFilmBackOperation, "postScale");
212 mSamp.addOp(postScale);
213
214 Alembic::AbcGeom::FilmBackXformOp cameraScale(
215 Alembic::AbcGeom::kScaleFilmBackOperation, "cameraScale");
216 mSamp.addOp(cameraScale);
217
218 }
219
220 std::size_t filmBackIndex = 0;
221
222 switch (mFilmFit)
223 {
224 case MFnCamera::kFillFilmFit:
225 {
226 if (mSamp.getLensSqueezeRatio() > 1.0)
227 {
228 mSamp[0].setChannelValue(0, 1.0/mSamp.getLensSqueezeRatio());
229 mSamp[0].setChannelValue(1, 1.0);
230 }
231 else
232 {
233 mSamp[0].setChannelValue(0, 1.0);
234 mSamp[0].setChannelValue(1, mSamp.getLensSqueezeRatio());
235 }
236 filmBackIndex = 1;
237 }
238 break;
239
240 case MFnCamera::kHorizontalFilmFit:
241 {
242 if (mSamp.getLensSqueezeRatio() > 1.0)
243 {
244 mSamp[0].setChannelValue(0, 1.0);
245 mSamp[0].setChannelValue(1, mSamp.getLensSqueezeRatio());
246 mSamp[1].setChannelValue(0, 0.0);
247 mSamp[1].setChannelValue(1, 2.0 *
248 mfnCamera.filmFitOffset()/
249 mfnCamera.horizontalFilmAperture() );
250 }
251 else
252 {
253 mSamp[0].setChannelValue(0, 1.0);
254 mSamp[0].setChannelValue(1, 1.0);
255 mSamp[1].setChannelValue(0, 0.0);
256 mSamp[1].setChannelValue(1, 0.0);
257 }
258 filmBackIndex = 2;
259 }
260 break;
261
262 case MFnCamera::kVerticalFilmFit:
263 {
264 if (1.0/mSamp.getLensSqueezeRatio() > 1.0)
265 {
266 mSamp[0].setChannelValue(0, 1.0/mSamp.getLensSqueezeRatio());
267 mSamp[0].setChannelValue(1, 1.0);
268 mSamp[1].setChannelValue(0, 2.0 *
269 mfnCamera.filmFitOffset() /
270 mfnCamera.horizontalFilmAperture() );
271 mSamp[1].setChannelValue(1, 0.0);
272 }
273 else
274 {
275 mSamp[0].setChannelValue(0, 1.0);
276 mSamp[0].setChannelValue(1, 1.0);
277 mSamp[1].setChannelValue(0, 0.0);
278 mSamp[1].setChannelValue(1, 0.0);
279 }
280 filmBackIndex = 2;
281 }
282 break;
283
284 case MFnCamera::kOverscanFilmFit:
285 {
286 if (mSamp.getLensSqueezeRatio() < 1.0)
287 {
288 mSamp[0].setChannelValue(0, 1.0);
289 mSamp[0].setChannelValue(1, mSamp.getLensSqueezeRatio());
290 }
291 else
292 {
293 mSamp[0].setChannelValue(0, 1.0/mSamp.getLensSqueezeRatio());
294 mSamp[0].setChannelValue(1, 1.0);
295 }
296 filmBackIndex = 1;
297 }
298 break;
299
300 default:
301 break;
302 }
303
304 mSamp[filmBackIndex].setChannelValue(0, 1.0/mfnCamera.preScale());
305 mSamp[filmBackIndex].setChannelValue(1, 1.0/mfnCamera.preScale());
306
307 mSamp[filmBackIndex+1].setChannelValue(0, mfnCamera.filmTranslateH());
308 mSamp[filmBackIndex+1].setChannelValue(1, mfnCamera.filmTranslateV());
309
310 mSamp[filmBackIndex+2].setChannelValue(0, 1.0/mfnCamera.postScale());
311 mSamp[filmBackIndex+2].setChannelValue(1, 1.0/mfnCamera.postScale());
312
313 mSamp[filmBackIndex+3].setChannelValue(0, mfnCamera.cameraScale());
314 mSamp[filmBackIndex+3].setChannelValue(1, mfnCamera.cameraScale());
315
316 mSchema.set(mSamp);
317 }
318
isAnimated() const319 bool MayaCameraWriter::isAnimated() const
320 {
321 return mIsAnimated || (mAttrs != NULL && mAttrs->isAnimated());
322 }
323