OLD | NEW |
(Empty) | |
| 1 //-***************************************************************************** |
| 2 // |
| 3 // Copyright (c) 2009-2011, |
| 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 <maya/MString.h> |
| 38 #include <maya/MDagPath.h> |
| 39 #include <maya/MDoubleArray.h> |
| 40 #include <maya/MPointArray.h> |
| 41 #include <maya/MFnNurbsSurface.h> |
| 42 #include <maya/MFnNurbsCurve.h> |
| 43 #include <maya/MGlobal.h> |
| 44 #include <maya/MObjectArray.h> |
| 45 #include <maya/MTrimBoundaryArray.h> |
| 46 #include <maya/MFnTransform.h> |
| 47 #include <maya/MCommandResult.h> |
| 48 #include <maya/MDagModifier.h> |
| 49 |
| 50 #include "util.h" |
| 51 #include "NurbsSurfaceHelper.h" |
| 52 #include "NodeIteratorVisitorHelper.h" |
| 53 |
| 54 namespace |
| 55 { |
| 56 |
| 57 // This function repacks trim curves information back into Maya format |
| 58 void trimSurface( Alembic::AbcGeom::INuPatchSchema::Sample & iSamp, |
| 59 MFnNurbsSurface & iFnSurface) |
| 60 { |
| 61 |
| 62 Alembic::Util::int32_t numLoops = iSamp.getTrimNumLoops(); |
| 63 if (numLoops == 0) |
| 64 return; |
| 65 |
| 66 MTrimBoundaryArray trimBoundaryArray; |
| 67 MObjectArray deleteAfterTrim; |
| 68 |
| 69 // this is for getting V back into Maya's coordinate system |
| 70 double startU, endU, startV, endV; |
| 71 iFnSurface.getKnotDomain(startU, endU, startV, endV); |
| 72 double offsetV = startV + endV; |
| 73 |
| 74 MStatus status = MS::kSuccess; |
| 75 |
| 76 Alembic::Abc::Int32ArraySamplePtr numCurvesPerLoop = |
| 77 iSamp.getTrimNumCurves(); |
| 78 Alembic::Abc::Int32ArraySamplePtr numCurveVerts = |
| 79 iSamp.getTrimNumVertices(); |
| 80 Alembic::Abc::Int32ArraySamplePtr orders = iSamp.getTrimOrders(); |
| 81 Alembic::Abc::FloatArraySamplePtr knots = iSamp.getTrimKnots(); |
| 82 Alembic::Abc::FloatArraySamplePtr uVert = iSamp.getTrimU(); |
| 83 Alembic::Abc::FloatArraySamplePtr vVert = iSamp.getTrimV(); |
| 84 Alembic::Abc::FloatArraySamplePtr wVert = iSamp.getTrimW(); |
| 85 |
| 86 Alembic::Util::int32_t curCurve = 0; |
| 87 Alembic::Util::int32_t curPos = 0; |
| 88 Alembic::Util::int32_t curKnot = 0; |
| 89 |
| 90 for (Alembic::Util::int32_t i = 0; i < numLoops; ++i) |
| 91 { |
| 92 MObjectArray trimLoop; |
| 93 |
| 94 Alembic::Util::int32_t numCurves = (*numCurvesPerLoop)[i]; |
| 95 for (Alembic::Util::int32_t j = 0; j < numCurves; ++j, ++curCurve) |
| 96 { |
| 97 unsigned int degree = (*orders)[curCurve] - 1; |
| 98 Alembic::Util::int32_t numVerts = (*numCurveVerts)[curCurve]; |
| 99 Alembic::Util::int32_t numKnots = numVerts + degree + 1; |
| 100 |
| 101 MPointArray cvs; |
| 102 cvs.setLength(numVerts); |
| 103 for (Alembic::Util::int32_t k=0 ; k<numVerts; ++k, ++curPos) |
| 104 { |
| 105 double x = (*uVert)[curPos]; |
| 106 double y = (*vVert)[curPos]; |
| 107 double w = (*wVert)[curPos]; |
| 108 cvs.set(k, x, offsetV-y, 0.0, w); |
| 109 } |
| 110 |
| 111 MDoubleArray dknots; |
| 112 dknots.setLength(numKnots - 2); |
| 113 ++curKnot; |
| 114 for (Alembic::Util::int32_t k = 1; k < numKnots - 1; |
| 115 ++k, ++curKnot) |
| 116 { |
| 117 dknots.set((*knots)[curKnot], k - 1); |
| 118 } |
| 119 ++curKnot; |
| 120 |
| 121 MFnNurbsCurve fnCurve; |
| 122 |
| 123 // when a 2D curve is created without a parent, the function |
| 124 // returns the transform node of the curve created. |
| 125 // The transform node as well as the curve node need to be |
| 126 // deleted once the trim is done, because after all this is not |
| 127 // the equivalent of "curveOnSurface" command |
| 128 MObject curve2D = fnCurve.create(cvs, dknots, degree, |
| 129 MFnNurbsCurve::kOpen, true, true, |
| 130 MObject::kNullObj, &status); |
| 131 |
| 132 if (status == MS::kSuccess) |
| 133 { |
| 134 MFnTransform trans(curve2D, &status); |
| 135 if (status == MS::kSuccess) |
| 136 { |
| 137 trimLoop.append(trans.child(0)); |
| 138 deleteAfterTrim.append(curve2D); |
| 139 } |
| 140 } |
| 141 } |
| 142 trimBoundaryArray.append(trimLoop); |
| 143 } |
| 144 |
| 145 if (iFnSurface.trimWithBoundaries(trimBoundaryArray) == MS::kSuccess) |
| 146 { |
| 147 unsigned int length = deleteAfterTrim.length(); |
| 148 for (unsigned int l=0; l<length; l++) |
| 149 { |
| 150 MGlobal::deleteNode(deleteAfterTrim[l]); |
| 151 } |
| 152 } |
| 153 else |
| 154 { |
| 155 MGlobal::displayError("Trimming Nurbs Surface failed."); |
| 156 } |
| 157 } |
| 158 } |
| 159 |
| 160 MObject readNurbs(double iFrame, Alembic::AbcGeom::INuPatch & iNode, |
| 161 MObject & iObject) |
| 162 { |
| 163 MStatus status; |
| 164 MObject obj; |
| 165 |
| 166 Alembic::AbcGeom::INuPatchSchema schema = iNode.getSchema(); |
| 167 |
| 168 // no interpolation for now |
| 169 Alembic::AbcCoreAbstract::index_t index, ceilIndex; |
| 170 double alpha = getWeightAndIndex(iFrame, schema.getTimeSampling(), |
| 171 schema.getNumSamples(), index, ceilIndex); |
| 172 |
| 173 Alembic::AbcGeom::INuPatchSchema::Sample samp; |
| 174 schema.get(samp, Alembic::Abc::ISampleSelector(index)); |
| 175 |
| 176 Alembic::Abc::V3fArraySamplePtr pos = samp.getPositions(); |
| 177 |
| 178 MString surfaceName(iNode.getName().c_str()); |
| 179 |
| 180 unsigned int degreeU = samp.getUOrder() - 1; |
| 181 unsigned int degreeV = samp.getVOrder() - 1; |
| 182 unsigned int numCVInU = samp.getNumU(); |
| 183 unsigned int numCVInV = samp.getNumV(); |
| 184 |
| 185 // cv points |
| 186 unsigned int numCV = numCVInU*numCVInV; |
| 187 unsigned int curPos = 0; |
| 188 |
| 189 MPointArray controlVertices; |
| 190 controlVertices.setLength(numCV); |
| 191 |
| 192 for (unsigned int v = 0; v < numCVInV; ++v) |
| 193 { |
| 194 for (unsigned int u = 0; u < numCVInU; ++u, ++curPos) |
| 195 { |
| 196 unsigned int mayaIndex = u * numCVInV + (numCVInV - v - 1); |
| 197 MPoint pt((*pos)[curPos].x, (*pos)[curPos].y, (*pos)[curPos].z); |
| 198 |
| 199 // go from u,v order to reversed v, u order |
| 200 controlVertices.set(pt, mayaIndex); |
| 201 } |
| 202 } |
| 203 |
| 204 Alembic::Abc::FloatArraySamplePtr uKnot = samp.getUKnot(); |
| 205 Alembic::Abc::FloatArraySamplePtr vKnot = samp.getVKnot(); |
| 206 |
| 207 unsigned int numKnotsInU = uKnot->size() - 2; |
| 208 MDoubleArray uKnotSequences; |
| 209 uKnotSequences.setLength(numKnotsInU); |
| 210 for (unsigned int i = 0; i < numKnotsInU; ++i) |
| 211 { |
| 212 uKnotSequences.set((*uKnot)[i+1], i); |
| 213 } |
| 214 |
| 215 unsigned int numKnotsInV = vKnot->size() - 2; |
| 216 MDoubleArray vKnotSequences; |
| 217 vKnotSequences.setLength(numKnotsInV); |
| 218 for (unsigned int i = 0; i < numKnotsInV; i++) |
| 219 { |
| 220 vKnotSequences.set((*vKnot)[i+1], i); |
| 221 } |
| 222 |
| 223 // Node creation try the API first |
| 224 MFnNurbsSurface mFn; |
| 225 obj = mFn.create(controlVertices, uKnotSequences, vKnotSequences, |
| 226 degreeU, degreeV, MFnNurbsSurface::kOpen, MFnNurbsSurface::kOpen, |
| 227 true, iObject, &status); |
| 228 |
| 229 if (status == MS::kSuccess) |
| 230 { |
| 231 mFn.setName(surfaceName); |
| 232 } |
| 233 else |
| 234 { |
| 235 MString errorMsg = "Could not create Nurbs Surface: "; |
| 236 errorMsg += surfaceName; |
| 237 MGlobal::displayError(errorMsg); |
| 238 } |
| 239 |
| 240 trimSurface(samp, mFn); |
| 241 |
| 242 return obj; |
| 243 } |
| 244 |
| 245 MObject createNurbs(double iFrame, Alembic::AbcGeom::INuPatch & iNode, |
| 246 MObject & iParent) |
| 247 { |
| 248 // normally we'd only want to do the read if we had only 1 sample, but |
| 249 // since we can't seem to create an empty Nurbs surface like we can a mesh |
| 250 // we will read the data (eventually multiple times on creation) |
| 251 MObject obj = readNurbs(iFrame, iNode, iParent); |
| 252 |
| 253 if (!obj.isNull()) |
| 254 { |
| 255 MFnNurbsSurface fn(obj); |
| 256 setInitialShadingGroup(fn.partialPathName()); |
| 257 } |
| 258 |
| 259 return obj; |
| 260 } |
OLD | NEW |