bool BasicLocator::getCirclePoints( MPointArray &pts ) const { MStatus stat; MObject thisNode = thisMObject(); MFnDagNode dagFn( thisNode ); MPlug xWidthPlug = dagFn.findPlug( xWidth, &stat ); float xWidthValue; xWidthPlug.getValue( xWidthValue ); MPlug zWidthPlug = dagFn.findPlug( zWidth, &stat ); float zWidthValue; zWidthPlug.getValue( zWidthValue ); MPlug typePlug = dagFn.findPlug( dispType, &stat ); short typeValue; typePlug.getValue( typeValue ); unsigned int nCirclePts; switch( typeValue ) { case 0: nCirclePts = 4; break; case 1: nCirclePts = 5; break; default: nCirclePts = 20; break; } pts.clear(); pts.setSizeIncrement( nCirclePts ); MPoint pt; pt.y = 0.0; const double angleIncr = M_2PI / (nCirclePts - 1); double angle = 0.0; unsigned int i=0; for( ; i < nCirclePts; i++, angle+=angleIncr ) { pt.x = xWidthValue * cos( angle ); pt.z = zWidthValue * sin( angle ); pts.append( pt ); } return true; }
MStatus helix2::undoIt() { MStatus status; MFnNurbsCurve curveFn( fDagPath ); status = curveFn.setCVs( fCVs ); if ( MS::kSuccess != status) { cerr << "undoIt: array length is " << fCVs.length() << "bad status: " << status << endl; return status; } status = curveFn.updateCurve(); if ( MS::kSuccess != status ) { cerr << "undoIt: updateCurve() failed status: " << status << endl; return status; } fCVs.clear(); return MS::kSuccess; }
MStatus helix2::redoIt() { unsigned i, numCVs; MStatus status; MFnNurbsCurve curveFn( fDagPath ); numCVs = curveFn.numCVs(); status = curveFn.getCVs( fCVs ); if ( MS::kSuccess != status ) { cerr << "redoIt: could not get cvs status: " << status << endl; return MS::kFailure; } MPointArray points(fCVs); for (i = 0; i < numCVs; i++) points[i] = MPoint( radius * cos( (double)i ), pitch * (double)i, radius * sin( (double)i ) ); status = curveFn.setCVs( points ); if ( MS::kSuccess != status ) { cerr << "redoIt: could not setCVs status: " << status << endl; fCVs.clear(); return status; } status = curveFn.updateCurve(); if ( MS::kSuccess != status ) { cerr << "redoIt: updateCurve() failed status: " << status << endl; return status; } return MS::kSuccess; }
void TestDeformer::initVertMapping(MDataBlock& data, MItGeometry& iter, const MMatrix& localToWorldMatrix, unsigned int mIndex) { MStatus status; MArrayDataHandle vertMapOutArrayData = data.outputArrayValue( vert_map, &status ); CHECK_MSTATUS( status ); // use vertMapOutArrayBuilder to modify vertMapOutArrayData iter.reset(); int count = iter.count(); MArrayDataBuilder vertMapOutArrayBuilder( vert_map, count, &status ); CHECK_MSTATUS( status ); MPointArray allPts;// world vertex position of the driven mesh allPts.clear(); // walk through the driven mesh /// copy MItGeometry's vertex to vertMapOutArrayData int i = 0; while( !iter.isDone(&status) ) { CHECK_MSTATUS( status ); MDataHandle initIndexDataHnd = vertMapOutArrayBuilder.addElement( i, &status ); CHECK_MSTATUS( status ); int negIndex = -1; initIndexDataHnd.setInt( negIndex ); initIndexDataHnd.setClean(); // append a vertex position(world coordination) to allPts CHECK_MSTATUS(allPts.append( iter.position() * localToWorldMatrix )); i = i+1; iter.next(); } CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder )); /// Append more vertex from each driver mesh to vertMapOutArrayData MArrayDataHandle meshAttrHandle = data.inputArrayValue( driver_mesh, &status ); CHECK_MSTATUS( status ); int numMeshes = meshAttrHandle.elementCount(); __debug("%s(), numMeshes=%d", __FUNCTION__, numMeshes); CHECK_MSTATUS(meshAttrHandle.jumpToElement(0)); for( int meshIndex=0; meshIndex < numMeshes; ++meshIndex ) { __debug("%s(), meshIndex=%d", __FUNCTION__, meshIndex); MDataHandle currentMesh = meshAttrHandle.inputValue(&status); CHECK_MSTATUS(status); MObject meshMobj = currentMesh.asMesh(); __debug("%s(), meshMobj.apiTypeStr()=%s", __FUNCTION__, meshMobj.apiTypeStr()); __debugMeshInfo(__FUNCTION__, meshMobj); { _initVertMapping_on_one_mesh(meshMobj, vertMapOutArrayBuilder, allPts);// Note: vertMapOutArrayBuilder is updated in this function! //CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder )); } if( !meshAttrHandle.next() ) { break; } }// for (mesh CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder )); }
MStatus mshUtil::doIt( const MArgList& args ) { MString objname, mcfname; MArgDatabase argData(syntax(), args); MSelectionList selList; MGlobal::getActiveSelectionList ( selList ); if ( selList.length() < 2 ) { MGlobal:: displayError ( "Not sufficient selection!" ); return MS::kSuccess; } MItSelectionList iter( selList ); iter.reset(); MDagPath meshPath; iter.getDagPath( meshPath ); meshPath.extendToShape(); MObject meshObj = meshPath.node(); MString surface = meshPath.partialPathName(); MStatus status; MFnMesh meshFn(meshPath, &status ); if(!status) { MGlobal:: displayError ( "Not sufficient selection!" ); return MS::kSuccess; } MPointArray vxa; meshFn.getPoints (vxa, MSpace::kWorld); MPoint cenfrom(0.f, 0.f, 0.f); for(unsigned i=0; i<vxa.length(); i++) cenfrom += vxa[i]; cenfrom = cenfrom/(float)vxa.length(); iter.next(); iter.getDagPath( meshPath ); meshPath.extendToShape(); MFnMesh mesh1Fn(meshPath, &status ); if(!status) { MGlobal:: displayError ( "Not sufficient selection!" ); return MS::kSuccess; } vxa.clear(); mesh1Fn.getPoints (vxa, MSpace::kWorld); MPoint cento(0.f, 0.f, 0.f); for(unsigned i=0; i<vxa.length(); i++) cento += vxa[i]; cento = cento/(float)vxa.length(); MVector diff = cento - cenfrom; MDoubleArray res; res.append(diff.x); res.append(diff.y); res.append(diff.z); setResult ( res ); /* if ( !argData.isFlagSet("-i") || !argData.isFlagSet("-o") ) { //MGlobal::displayError( "No .obj or .mcf file specified to translate! Example: mshUtil -i filename.obj -o filename.mcf" ); return MS::kSuccess; } else { argData.getFlagArgument("-i", 0, objname); argData.getFlagArgument("-o", 0, mcfname); return MS::kSuccess; } */ return MS::kSuccess; }
MStatus Molecule3Cmd::redoIt() { MStatus stat; MDagPath dagPath; MFnMesh meshFn; // Create a ball int nBallPolys; MPointArray ballVerts; MIntArray ballPolyCounts; MIntArray ballPolyConnects; MFloatArray ballUCoords; MFloatArray ballVCoords; MIntArray ballFvUVIDs; genBall( MPoint::origin, ballRodRatio * radius.value(), segs, nBallPolys, ballVerts, ballPolyCounts, ballPolyConnects, true, ballUCoords, ballVCoords, ballFvUVIDs ); unsigned int i, j, vertOffset; MPointArray meshVerts; MPoint p0, p1; MObject objTransform; // Setup for rods int nRodPolys; MPointArray rodVerts; MIntArray rodPolyCounts; MIntArray rodPolyConnects; MFloatArray rodUCoords; MFloatArray rodVCoords; MIntArray rodFvUVIDs; // Setup for newMesh int nNewPolys; MPointArray newVerts; MIntArray newPolyCounts; MIntArray newPolyConnects; MFloatArray newUCoords; MFloatArray newVCoords; MIntArray newFvUVIDs; int uvOffset; MDagModifier dagMod; MFnDagNode dagFn; objTransforms.clear(); // Iterate over the meshes unsigned int mi; for( mi=0; mi < selMeshes.length(); mi++ ) { dagPath = selMeshes[mi]; meshFn.setObject( dagPath ); uvOffset = 0; nNewPolys = 0; newVerts.clear(); newPolyCounts.clear(); newPolyConnects.clear(); newUCoords.clear(); newVCoords.clear(); newFvUVIDs.clear(); // Generate balls meshFn.getPoints( meshVerts, MSpace::kWorld ); for( i=0; i < meshVerts.length(); i++ ) { vertOffset = newVerts.length(); // Add the ball to the new mesh nNewPolys += nBallPolys; // Move the ball vertices to the mesh vertex. Add it to the newMesh for( j=0; j < ballVerts.length(); j++ ) newVerts.append( meshVerts[i] + ballVerts[j] ); for( j=0; j < ballPolyCounts.length(); j++ ) newPolyCounts.append( ballPolyCounts[j] ); for( j=0; j < ballPolyConnects.length(); j++ ) newPolyConnects.append( vertOffset + ballPolyConnects[j] ); // Only add the uv coordinates once, since they are shared // by all balls if( i == 0 ) { for( j=0; j < ballUCoords.length(); j++ ) { newUCoords.append( ballUCoords[j] ); newVCoords.append( ballVCoords[j] ); } } for( j=0; j < ballFvUVIDs.length(); j++ ) { newFvUVIDs.append( uvOffset + ballFvUVIDs[j] ); } } uvOffset = newUCoords.length(); // Generate rods int nRods = 0; MItMeshEdge edgeIter( dagPath ); for( ; !edgeIter.isDone(); edgeIter.next(), nRods++ ) { p0 = edgeIter.point( 0, MSpace::kWorld ); p1 = edgeIter.point( 1, MSpace::kWorld ); // N.B. Generate the uv coordinates only once since they // are referenced by all rods genRod( p0, p1, radius.value(), segs, nRodPolys, rodVerts, rodPolyCounts, rodPolyConnects, nRods == 0, rodUCoords, rodVCoords, rodFvUVIDs ); vertOffset = newVerts.length(); // Add the rod to the mesh nNewPolys += nRodPolys; for( i=0; i < rodVerts.length(); i++ ) newVerts.append( rodVerts[i] ); for( i=0; i < rodPolyCounts.length(); i++ ) newPolyCounts.append( rodPolyCounts[i] ); for( i=0; i < rodPolyConnects.length(); i++ ) newPolyConnects.append( vertOffset + rodPolyConnects[i] ); // First rod if( nRods == 0 ) { // Add rod's uv coordinates to the list for( i=0; i < rodUCoords.length(); i++ ) { newUCoords.append( rodUCoords[i] ); newVCoords.append( rodVCoords[i] ); } } // Set the face-vertex-uvIDs for( i=0; i < rodFvUVIDs.length(); i++ ) { newFvUVIDs.append( uvOffset + rodFvUVIDs[i] ); } } objTransform = meshFn.create( newVerts.length(), nNewPolys, newVerts, newPolyCounts, newPolyConnects, newUCoords, newVCoords, MObject::kNullObj, &stat ); if( !stat ) { MGlobal::displayError( MString( "Unable to create mesh: " ) + stat.errorString() ); return stat; } objTransforms.append( objTransform ); meshFn.assignUVs( newPolyCounts, newFvUVIDs ); meshFn.updateSurface(); // Rename transform node dagFn.setObject( objTransform ); dagFn.setName( "molecule" ); // Put mesh into the initial shading group dagMod.commandToExecute( MString( "sets -e -fe initialShadingGroup " ) + meshFn.name() ); } // Select all the newly created molecule meshes MString cmd( "select -r" ); for( i=0; i < objTransforms.length(); i++ ) { dagFn.setObject( objTransforms[i] ); cmd += " " + dagFn.name(); } dagMod.commandToExecute( cmd ); return dagMod.doIt(); }
MStatus genRod( const MPoint &p0, const MPoint &p1, const double radius, const unsigned int nSegs, int &nPolys, MPointArray &verts, MIntArray &polyCounts, MIntArray &polyConnects ) { verts.clear(); polyCounts.clear(); polyConnects.clear(); unsigned int nCirclePts = nSegs; unsigned int nVerts = 2 * nCirclePts; // Calculate the local axiis of the rod MVector vec( p1 - p0 ); MVector up( 0.0, 1.0, 0.0 ); MVector xAxis, yAxis, zAxis; yAxis = vec.normal(); if( up.isParallel( yAxis, 0.1 ) ) up = MVector( 1.0, 0.0, 0.0 ); xAxis = yAxis ^ up; zAxis = (xAxis ^ yAxis).normal(); xAxis = (yAxis ^ zAxis ).normal(); // Calculate the vertex positions verts.setLength( nVerts ); double angleIncr = 2.0 * M_PI / nSegs; double angle; MPoint p; double x, z; unsigned int i; for( i=0, angle=0; i < nCirclePts; i++, angle += angleIncr ) { // Calculate position in circle x = radius * cos( angle ); z = radius * sin( angle ); p = p0 + x * xAxis + z * zAxis; verts[ i ] = p; p += vec; verts[ i + nCirclePts ] = p; } nPolys = nSegs; // Generate polycounts polyCounts.setLength( nPolys ); for( i=0; i < polyCounts.length(); i++ ) polyCounts[i] = 4; // Generate polyconnects polyConnects.setLength( nPolys * 4 ); polyConnects.clear(); for( i=0; i < nSegs; i++ ) { polyConnects.append( linearIndex( 0, i, 2, nCirclePts ) ); polyConnects.append( linearIndex( 0, i+1, 2, nCirclePts ) ); polyConnects.append( linearIndex( 1, i+1, 2, nCirclePts ) ); polyConnects.append( linearIndex( 1, i, 2, nCirclePts ) ); } return MS::kSuccess; }
MStatus genBall( const MPoint ¢re, const double radius, const unsigned int nSegs, int &nPolys, MPointArray &verts, MIntArray &polyCounts, MIntArray &polyConnects ) { verts.clear(); polyCounts.clear(); polyConnects.clear(); int nAzimuthSegs = nSegs * 2; int nZenithSegs = nSegs; int nAzimuthPts = nAzimuthSegs; // Last point corresponds to the first int nZenithPts = nZenithSegs + 1; // Last point is at other pole double azimIncr = 2.0 * M_PI / nAzimuthSegs; double zenIncr = M_PI / nZenithSegs; MPoint p; double azimuth, zenith; double sinZenith; int azi, zeni; zenith = 0.0; for( zeni=0; zeni < nZenithPts; zeni++, zenith += zenIncr ) { azimuth = 0.0; for( azi=0; azi < nAzimuthPts; azi++, azimuth += azimIncr ) { sinZenith = sin(zenith); p.x = radius * sinZenith * cos(azimuth); p.y = radius * cos(zenith); p.z = radius * sinZenith * sin(azimuth); verts.append( p ); } } // Calculate the number of polygons nPolys = nAzimuthSegs * nZenithSegs; // Each face has four points polyCounts.setLength( nPolys ); int i; for( i=0; i < nPolys; i++ ) polyCounts[i] = 4; // Generate the faces for( zeni=0; zeni < nZenithSegs; zeni++ ) { for( azi=0; azi < nAzimuthSegs; azi++ ) { //MGlobal::displayInfo( MString( "\n" ) + azi + "," + zeni ); polyConnects.append( linearIndex( zeni, azi, nZenithPts, nAzimuthPts ) ); polyConnects.append( linearIndex( zeni, azi+1, nZenithPts, nAzimuthPts ) ); polyConnects.append( linearIndex( zeni+1, azi+1, nZenithPts, nAzimuthPts ) ); polyConnects.append( linearIndex( zeni+1, azi, nZenithPts, nAzimuthPts ) ); } } return MS::kSuccess; }
MStatus cvColor::initialize() { MStatus stat; MFnNumericAttribute numericAttr; MFnTypedAttribute typedAttr; drawingEnabled = numericAttr.create( "drawingEnabled", "en", MFnNumericData::kBoolean, 1, &stat ); if (!stat) { stat.perror("create drawingEnabled attribute"); return stat; } pointSize = numericAttr.create( "pointSize", "ps", MFnNumericData::kFloat, 4.0, &stat ); if (!stat) { stat.perror("create pointSize attribute"); return stat; } inputSurface = typedAttr.create( "inputSurface", "is", MFnNurbsSurfaceData::kNurbsSurface, &stat); if (!stat) { stat.perror("create inputSurface attribute"); return stat; } cvLocations = typedAttr.create( "cvLocations", "cv", MFnPointArrayData::kPointArray, &stat); if (!stat) { stat.perror("create cvLocations attribute"); return stat; } MPointArray defaultPoints; MFnPointArrayData defaultArray; MObject defaultAttr; defaultPoints.clear(); // Empty array defaultAttr = defaultArray.create (defaultPoints); stat = typedAttr.setDefault(defaultAttr); if (!stat) { stat.perror("could not create default output attribute"); return stat; } stat = addAttribute (drawingEnabled); if (!stat) { stat.perror("addAttribute"); return stat;} stat = addAttribute (pointSize); if (!stat) { stat.perror("addAttribute"); return stat;} stat = addAttribute (inputSurface); if (!stat) { stat.perror("addAttribute"); return stat;} stat = addAttribute (cvLocations); if (!stat) { stat.perror("addAttribute"); return stat;} stat = attributeAffects( inputSurface, cvLocations ); if (!stat) { stat.perror("attributeAffects"); return stat;} stat = attributeAffects( drawingEnabled, cvLocations ); if (!stat) { stat.perror("attributeAffects"); return stat;} stat = attributeAffects( pointSize, cvLocations ); if (!stat) { stat.perror("attributeAffects"); return stat;} return MS::kSuccess; }
void curveColliderLocator::draw(M3dView &view, const MDagPath &path, M3dView::DisplayStyle style, M3dView::DisplayStatus status) { // // Get the input curve // MObject thisNode = thisMObject(); MPlug radiusPlug(thisNode, colliderRadiusIn); MPlug colorPlugR(thisNode, colliderColorR); MPlug colorPlugG(thisNode, colliderColorG); MPlug colorPlugB(thisNode, colliderColorB); MPlug colorPlugT(thisNode, colliderTransparency); MPlug radiusElement; double radius; double radius2; double param; double param2; double paramNorm; radiusPlug.getValue(radius); MStatus stat; MQuaternion rotateQuat; double degreesToRadians = ( M_PI/ 180.0 ); double radiansToDegrees = ( 180.0/M_PI ); double rotateRadians; MVector crvNormalRotated; MPointArray radiusPts; MPoint radiusPt; // Alternate method of getting the MFnNurbsCurve: MPlug curvePlug(thisNode, colliderCurveIn); MPlugArray inputCrvArray; curvePlug.connectedTo(inputCrvArray, true, false); MObject crvColliderObj = inputCrvArray[0].node(); MFnNurbsCurve cColliderFn(crvColliderObj, &stat); if(!stat){ MGlobal::displayInfo(MString("Error creating MFnNurbsCurve for collider curve")); return; } MFnDagNode crvDagNode(crvColliderObj); MDagPath crvDagPath; crvDagNode.getPath(crvDagPath); MMatrix crvXform = crvDagPath.inclusiveMatrix(); int numSpans = cColliderFn.numSpans(); MPoint crvPoint; MPoint crvPoint2; GLUquadricObj* qobj = gluNewQuadric(); view.beginGL(); ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // DRAW SMOOTH SHADED ///////////////////////////////////////////////////////////////////////////////////////////////////////////// if ( ( style == M3dView::kFlatShaded ) || ( style == M3dView::kGouraudShaded ) ) { glPushAttrib( GL_ALL_ATTRIB_BITS ); glShadeModel(GL_SMOOTH); glEnable(GL_LIGHTING); glEnable(GL_BLEND); glEnable(GL_LIGHT0); glMatrixMode( GL_MODELVIEW ); float3 color; colorPlugR.getValue(color[0]); colorPlugG.getValue(color[1]); colorPlugB.getValue(color[2]); float transparency; colorPlugT.getValue(transparency); float diffuse[] = {color[0], color[1], color[2], transparency}; float specular[] = { 0.7f, 0.7f, 0.7f, transparency}; float shine[] = { 100.0f }; float ambient[] = { 0.2f, 0.2f, 0.2f, transparency }; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shine); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); // Draw the beginning and ending sphere caps glPushMatrix(); cColliderFn.getPointAtParam(0, crvPoint, MSpace::kWorld); crvPoint = crvPoint*crvXform; glTranslatef(crvPoint.x, crvPoint.y, crvPoint.z); radiusElement = radiusPlug.elementByPhysicalIndex(0, &stat); radiusElement.getValue(radius); gluSphere(qobj, radius, 16, 16); glPopMatrix(); glPushMatrix(); cColliderFn.getPointAtParam(numSpans, crvPoint, MSpace::kWorld); crvPoint = crvPoint*crvXform; glTranslatef(crvPoint.x, crvPoint.y, crvPoint.z); radiusElement = radiusPlug.elementByPhysicalIndex( (radiusPlug.numElements() - 1), &stat); radiusElement.getValue(radius); gluSphere(qobj, radius, 16, 16); glPopMatrix(); int numStacks = numSpans*30; int numSlices = 32; // Initialize our point array with the radius values radiusPts.clear(); radiusPts.setLength(radiusPlug.numElements()); for(int radiusItr = 0; radiusItr < radiusPlug.numElements(); radiusItr++){ radiusElement = radiusPlug.elementByPhysicalIndex(radiusItr, &stat); if(!stat){MGlobal::displayError(MString("Could not get radius element.")); return;} radiusElement.getValue(radius); radiusPt.x = (double)radius; radiusPt.y = 0.0; radiusPt.z = 0.0; radiusPts[radiusItr] = radiusPt; } if(numStacks>1){ for(uint crvItr = 0; crvItr < numStacks - 1; crvItr++){ param = (float(crvItr)/float(numStacks-1))*numSpans; param2 = (float(crvItr+1)/float(numStacks-1))*numSpans; cColliderFn.getPointAtParam(param, crvPoint, MSpace::kWorld); crvPoint = crvPoint*crvXform; cColliderFn.getPointAtParam(param2, crvPoint2, MSpace::kWorld); crvPoint2 = crvPoint2 * crvXform; // Determine the radius value int lastRadiusIndex = radiusPlug.numElements() - 1; if(lastRadiusIndex == 0){ radiusElement = radiusPlug.elementByPhysicalIndex(0, &stat); if(!stat){MGlobal::displayError(MString("Could not get radius element.")); return;} radiusElement.getValue(radius); radius2 = radius; }else if(lastRadiusIndex > 0){ paramNorm = param/numSpans; radiusPt = getInterpolatedSplinePoint(paramNorm, radiusPts); radius = radiusPt.x; paramNorm = param2/numSpans; radiusPt = getInterpolatedSplinePoint(paramNorm, radiusPts); radius2 = radiusPt.x; } // First, we need to determine our starting position by travelling along the normal MVector crvNormal = cColliderFn.normal(param, MSpace::kWorld); crvNormal = crvNormal * crvXform; MVector crvTangent = cColliderFn.tangent(param, MSpace::kWorld); crvTangent = crvTangent * crvXform; crvNormal.normalize(); crvTangent.normalize(); MVector crvNormal2 = cColliderFn.normal(param2, MSpace::kWorld); crvNormal2 = crvNormal2 * crvXform; MVector crvTangent2 = cColliderFn.tangent(param2, MSpace::kWorld); crvTangent2 = crvTangent2 * crvXform; crvNormal2.normalize(); crvTangent2.normalize(); // glTranslatef(crvNormal.x, crvNormal.y, crvNormal.z); glBegin(GL_QUADS); for(int sliceItr = 0; sliceItr < numSlices; sliceItr++){ // quad vertex 4 rotateRadians = ((((float)sliceItr+1)/numSlices)*360)*degreesToRadians; rotateQuat.setAxisAngle(crvTangent, rotateRadians); crvNormalRotated = crvNormal.rotateBy(rotateQuat); glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z ); glVertex3f((float)crvPoint.x + (crvNormalRotated.x*radius), (float)crvPoint.y + (crvNormalRotated.y*radius), (float)crvPoint.z + (crvNormalRotated.z*radius)); // quad vertex 3 rotateRadians = ((((float)sliceItr+1)/numSlices)*360)*degreesToRadians; rotateQuat.setAxisAngle(crvTangent2, rotateRadians); crvNormalRotated = crvNormal.rotateBy(rotateQuat); glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z ); glVertex3f((float)crvPoint2.x + (crvNormalRotated.x*radius2), (float)crvPoint2.y + (crvNormalRotated.y*radius2), (float)crvPoint2.z + (crvNormalRotated.z*radius2)); // quad vertex 2 rotateRadians = (((float)sliceItr/numSlices)*360)*degreesToRadians; rotateQuat.setAxisAngle(crvTangent2, rotateRadians); crvNormalRotated = crvNormal.rotateBy(rotateQuat); glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z ); glVertex3f((float)crvPoint2.x + (crvNormalRotated.x*radius2), (float)crvPoint2.y + (crvNormalRotated.y*radius2), (float)crvPoint2.z + (crvNormalRotated.z*radius2)); // quad vertex 1 rotateRadians = (((float)sliceItr/numSlices)*360)*degreesToRadians; rotateQuat.setAxisAngle(crvTangent, rotateRadians); crvNormalRotated = crvNormal.rotateBy(rotateQuat); glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z ); glVertex3f((float)crvPoint.x + (crvNormalRotated.x*radius), (float)crvPoint.y + (crvNormalRotated.y*radius), (float)crvPoint.z + (crvNormalRotated.z*radius)); } glEnd(); } } glPopAttrib(); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // END SMOOTH SHADED ///////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // DRAW WIREFRAME ///////////////////////////////////////////////////////////////////////////////////////////////////////////// if ( style == M3dView::kWireFrame || status == M3dView::kActive || status == M3dView::kLead) { glPushAttrib( GL_ALL_ATTRIB_BITS ); // Draw the beginning and ending sphere caps // Quadrilateral strips glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glPushMatrix(); cColliderFn.getPointAtParam(0, crvPoint, MSpace::kWorld); crvPoint = crvPoint*crvXform; glTranslatef(crvPoint.x, crvPoint.y, crvPoint.z); radiusElement = radiusPlug.elementByPhysicalIndex(0, &stat); radiusElement.getValue(radius); gluSphere(qobj, radius, 16, 16); glPopMatrix(); glPushMatrix(); cColliderFn.getPointAtParam(numSpans, crvPoint, MSpace::kWorld); crvPoint = crvPoint*crvXform; glTranslatef(crvPoint.x, crvPoint.y, crvPoint.z); radiusElement = radiusPlug.elementByPhysicalIndex( (radiusPlug.numElements() - 1), &stat); radiusElement.getValue(radius); gluSphere(qobj, radius, 16, 16); glPopMatrix(); int numStacks = numSpans*10; int numSlices = 32; // Initialize our point array with the radius values radiusPts.clear(); radiusPts.setLength(radiusPlug.numElements()); for(int radiusItr = 0; radiusItr < radiusPlug.numElements(); radiusItr++){ radiusElement = radiusPlug.elementByPhysicalIndex(radiusItr, &stat); if(!stat){MGlobal::displayError(MString("Could not get radius element.")); return;} radiusElement.getValue(radius); radiusPt.x = (double)radius; radiusPt.y = 0.0; radiusPt.z = 0.0; radiusPts[radiusItr] = radiusPt; } for(uint crvItr = 0; crvItr < numStacks; crvItr++){ param = (float(crvItr)/float(numStacks))*numSpans; param2 = (float(crvItr+1)/float(numStacks))*numSpans; cColliderFn.getPointAtParam(param, crvPoint, MSpace::kWorld); crvPoint = crvPoint*crvXform; cColliderFn.getPointAtParam(param2, crvPoint2, MSpace::kWorld); crvPoint2 = crvPoint2 * crvXform; // Determine the radius value int lastRadiusIndex = radiusPlug.numElements() - 1; if(lastRadiusIndex == 0){ radiusElement = radiusPlug.elementByPhysicalIndex(0, &stat); if(!stat){MGlobal::displayError(MString("Could not get radius element.")); return;} radiusElement.getValue(radius); radius2 = radius; }else if(lastRadiusIndex > 0){ paramNorm = param/numSpans; radiusPt = getInterpolatedSplinePoint(paramNorm, radiusPts); radius = radiusPt.x; paramNorm = param2/numSpans; radiusPt = getInterpolatedSplinePoint(paramNorm, radiusPts); radius2 = radiusPt.x; } // First, we need to determine our starting position by travelling along the normal MVector crvNormal = cColliderFn.normal(param, MSpace::kWorld); crvNormal = crvNormal * crvXform; MVector crvTangent = cColliderFn.tangent(param, MSpace::kWorld); crvTangent = crvTangent * crvXform; crvNormal.normalize(); crvTangent.normalize(); MVector crvNormal2 = cColliderFn.normal(param2, MSpace::kWorld); crvNormal2 = crvNormal2 * crvXform; MVector crvTangent2 = cColliderFn.tangent(param2, MSpace::kWorld); crvTangent2 = crvTangent2 * crvXform; crvNormal2.normalize(); crvTangent2.normalize(); // glTranslatef(crvNormal.x, crvNormal.y, crvNormal.z); glBegin(GL_LINE_LOOP); for(int sliceItr = 0; sliceItr < numSlices; sliceItr++){ // quad vertex 4 rotateRadians = ((((float)sliceItr+1)/numSlices)*360)*degreesToRadians; rotateQuat.setAxisAngle(crvTangent, rotateRadians); crvNormalRotated = crvNormal.rotateBy(rotateQuat); glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z ); glVertex3f((float)crvPoint.x + (crvNormalRotated.x*radius), (float)crvPoint.y + (crvNormalRotated.y*radius), (float)crvPoint.z + (crvNormalRotated.z*radius)); // quad vertex 3 rotateRadians = ((((float)sliceItr+1)/numSlices)*360)*degreesToRadians; rotateQuat.setAxisAngle(crvTangent2, rotateRadians); crvNormalRotated = crvNormal.rotateBy(rotateQuat); glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z ); glVertex3f((float)crvPoint2.x + (crvNormalRotated.x*radius2), (float)crvPoint2.y + (crvNormalRotated.y*radius2), (float)crvPoint2.z + (crvNormalRotated.z*radius2)); // quad vertex 2 rotateRadians = (((float)sliceItr/numSlices)*360)*degreesToRadians; rotateQuat.setAxisAngle(crvTangent2, rotateRadians); crvNormalRotated = crvNormal.rotateBy(rotateQuat); glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z ); glVertex3f((float)crvPoint2.x + (crvNormalRotated.x*radius2), (float)crvPoint2.y + (crvNormalRotated.y*radius2), (float)crvPoint2.z + (crvNormalRotated.z*radius2)); // quad vertex 1 rotateRadians = (((float)sliceItr/numSlices)*360)*degreesToRadians; rotateQuat.setAxisAngle(crvTangent, rotateRadians); crvNormalRotated = crvNormal.rotateBy(rotateQuat); glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z ); glVertex3f((float)crvPoint.x + (crvNormalRotated.x*radius), (float)crvPoint.y + (crvNormalRotated.y*radius), (float)crvPoint.z + (crvNormalRotated.z*radius)); } glEnd(); } glPopAttrib(); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // END WIREFRAME ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // glEnable(GL_LIGHT0); view.endGL(); }
MStatus CXRayObjectExport::ExportPart(CEditableObject* O, MDagPath& mdagPath, MObject& mComponent) { MStatus stat = MS::kSuccess; MSpace::Space space = MSpace::kWorld; MFnMesh fnMesh( mdagPath, &stat ); if ( MS::kSuccess != stat) { fprintf(stderr,"Failure in MFnMesh initialization.\n"); return MS::kFailure; } MString mdagPathNodeName = fnMesh.name(); MFnDagNode dagNode1(mdagPath); u32 pc = dagNode1.parentCount(); for(u32 ip=0;ip<pc;++ip) { MObject object_parent = dagNode1.parent(ip, &stat); if(object_parent.hasFn(MFn::kTransform)) { MFnTransform parent_transform(object_parent,&stat); if ( MS::kSuccess == stat) { mdagPathNodeName = parent_transform.name(); break; } } } MItMeshPolygon meshPoly( mdagPath, mComponent, &stat ); if ( MS::kSuccess != stat) { fprintf(stderr,"Failure in MItMeshPolygon initialization.\n"); return MS::kFailure; } MItMeshVertex vtxIter( mdagPath, mComponent, &stat ); if ( MS::kSuccess != stat) { fprintf(stderr,"Failure in MItMeshVertex initialization.\n"); return MS::kFailure; } // If the shape is instanced then we need to determine which // instance this path refers to. // int instanceNum = 0; if (mdagPath.isInstanced()) instanceNum = mdagPath.instanceNumber(); // Get a list of all shaders attached to this mesh MObjectArray rgShaders; MIntArray texMap; MStatus status; status = fnMesh.getConnectedShaders (instanceNum, rgShaders, texMap); if (status == MStatus::kFailure) { Log("! Unable to load shaders for mesh"); return (MStatus::kFailure); } XRShaderDataVec xr_data; { for ( int i=0; i<(int)rgShaders.length(); i++ ) { MObject shader = rgShaders[i]; xr_data.push_back(SXRShaderData()); SXRShaderData& D = xr_data.back(); status = parseShader(shader, D); if (status == MStatus::kFailure) { status.perror ("Unable to retrieve filename of texture"); continue; } } } CEditableMesh* MESH = new CEditableMesh(O); MESH->SetName(mdagPathNodeName.asChar()); O->AppendMesh(MESH); int objectIdx, length; // Find i such that objectGroupsTablePtr[i] corresponds to the // object node pointed to by mdagPath length = objectNodeNamesArray.length(); { for( int i=0; i<length; i++ ) { if( objectNodeNamesArray[i] == mdagPathNodeName ) { objectIdx = i; break; } } } // Reserve uv table { VMapVec& _vmaps = MESH->m_VMaps; _vmaps.resize (1); st_VMap*& VM = _vmaps.back(); VM = new st_VMap("Texture",vmtUV,false); } // write faces { using FaceVec = xr_vector<st_Face>; using FaceIt = FaceVec::iterator; VMapVec& _vmaps = MESH->m_VMaps; SurfFaces& _surf_faces = MESH->m_SurfFaces; VMRefsVec& _vmrefs = MESH->m_VMRefs; // temp variables FvectorVec _points; FaceVec _faces; U32Vec _sgs; int f_cnt = fnMesh.numPolygons(); _sgs.reserve (f_cnt); _faces.reserve (f_cnt); _vmrefs.reserve (f_cnt*3); // int lastSmoothingGroup = INITIALIZE_SMOOTHING; MPointArray rgpt; MIntArray rgint; PtLookupMap ptMap; CSurface* surf = 0; for ( ; !meshPoly.isDone(); meshPoly.next()){ // Write out the smoothing group that this polygon belongs to // We only write out the smoothing group if it is different // from the last polygon. // int compIdx = meshPoly.index(); int smoothingGroup = polySmoothingGroups[ compIdx ]; // for each polygon, first setup the reverse mapping // between object-relative vertex indices and face-relative // vertex indices ptMap.clear(); for (int i=0; i<(int)meshPoly.polygonVertexCount(); i++) ptMap.insert (PtLookupMap::value_type(meshPoly.vertexIndex(i), i) ); // verify polygon zero area if (meshPoly.zeroArea()){ status = MS::kFailure; Log("! polygon have zero area:",meshPoly.index()); return status; } // verify polygon zero UV area /* if (meshPoly.zeroUVArea()){ status = MS::kFailure; Log("! polygon have zero UV area:",meshPoly.index()); return status; } */ // verify polygon has UV information if (!meshPoly.hasUVs (&status)) { status = MS::kFailure; Log("! polygon is missing UV information:",meshPoly.index()); return status; } int cTri; // now iterate through each triangle on this polygon and create a triangle object in our list status = meshPoly.numTriangles (cTri); if (!status) { Log("! can't getting triangle count"); return status; } for (int i=0; i < cTri; i++) { // for each triangle, first get the triangle data rgpt.clear();//triangle vertices rgint.clear();//triangle vertex indices // triangles that come from object are retrieved in world space status = meshPoly.getTriangle (i, rgpt, rgint, MSpace::kWorld); if (!status) { Log("! can't getting triangle for mesh poly"); return status; } if ((rgpt.length() != 3) || (rgint.length() != 3)) { Msg("! 3 points not returned for triangle"); return MS::kFailure; } // Write out vertex/uv index information // R_ASSERT2(fnMesh.numUVs()>0,"Can't find uvmaps."); _faces.push_back(st_Face()); _sgs.push_back(smoothingGroup); //set_smooth set_smoth_flags( _sgs.back(), rgint ); st_Face& f_it = _faces.back(); for ( int vtx=0; vtx<3; vtx++ ) { // get face-relative vertex PtLookupMap::iterator mapIt; int vtLocal, vtUV; int vt = rgint[vtx]; mapIt = ptMap.find(vt); Fvector2 uv; if (mapIt == ptMap.end()){ Msg("! Can't find local index."); return MS::kFailure; } vtLocal = (*mapIt).second; status = meshPoly.getUVIndex (vtLocal, vtUV, uv.x, uv.y); if (!status) { Msg("! error getting UV Index for local vertex '%d' and object vertex '%d'",vtLocal,vt); return status; } // flip v-part uv.y=1.f-uv.y; f_it.pv[2-vtx].pindex = AppendVertex(_points,rgpt[vtx]); f_it.pv[2-vtx].vmref = _vmrefs.size(); _vmrefs.push_back (st_VMapPtLst()); st_VMapPtLst& vm_lst = _vmrefs.back(); vm_lst.count = 1; vm_lst.pts = xr_alloc<st_VMapPt>(vm_lst.count); vm_lst.pts[0].vmap_index= 0; vm_lst.pts[0].index = AppendUV(_vmaps.back(),uv); } // out face material int iTexture = texMap[meshPoly.index()]; if (iTexture<0) xrDebug::Fatal(DEBUG_INFO,"Can't find material for polygon: %d",meshPoly.index()); SXRShaderData& D= xr_data[iTexture]; int compIdx = meshPoly.index(); surf = MESH->Parent()->CreateSurface(getMaterialName(mdagPath, compIdx, objectIdx),D); if (!surf) return MStatus::kFailure; _surf_faces[surf].push_back(_faces.size()-1); } } { // copy from temp MESH->m_VertCount = _points.size(); MESH->m_FaceCount = _faces.size(); MESH->m_Vertices = xr_alloc<Fvector>(MESH->m_VertCount); Memory.mem_copy (MESH->m_Vertices,&*_points.begin(),MESH->m_VertCount*sizeof(Fvector)); MESH->m_Faces = xr_alloc<st_Face>(MESH->m_FaceCount); Memory.mem_copy (MESH->m_Faces,&*_faces.begin(),MESH->m_FaceCount*sizeof(st_Face)); MESH->m_SmoothGroups = xr_alloc<u32>(MESH->m_FaceCount); Memory.mem_copy (MESH->m_SmoothGroups,&*_sgs.begin(),MESH->m_FaceCount*sizeof(u32)); MESH->RecomputeBBox (); } if ((MESH->GetVertexCount()<4)||(MESH->GetFaceCount()<2)) { Log ("! Invalid mesh: '%s'. Faces<2 or Verts<4",*MESH->Name()); return MS::kFailure; } } return stat; }