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