Explore Subdivide Surface Algorithm Of Maya

Maya与RenderMan细分曲面UV映射问题
文章围绕Pixar RenderMan 12.5版本中细分曲面展开。引入ZBrush时,RenderMan与Maya、ZBrush在细分操作上不同,导致UV映射出现问题。提出用相同UV集,让RenderMan线性插值的解决方法。还提及迪士尼工作室在Maya中给细分曲面植毛等内容。

Have A Fun, Click to listen music and reading my article.

 

  The article in Pixar RenderMan 12.5 release note named "Hierarchical Subdivision Surfaces" shows that these is a switch "interpolateboundary" in new version of RenderMan support hierarchical editing subdivide surface. But when we introduce ZBrush in the production pipeline, the UV mapping would cause a disaster, that, what we see is not what we want. Because the subdivide operation applied to origin control polygon surface in Maya by RenderMan is quite different from Maya and ZBrush.

  The most easily method is, using the same UV mapping set, force RenderMan linear interpolate the UV set when we are using subdivide surface. The polygon mesh before import into ZBrush should smooth several time in maya. But this "smooth" operation should not affect the origin UV set, or else the displacement map and normal map export from ZBrush will not correctly map onto the control polygon mesh.

  The  authors from Utah University and Disney Studio show us a secret sentence in "Exact Evaluation of Catmull-Clark Subdivision Surfaces Near B-spline Boundaries", "Evaluation near boundaries was evidently implemented in Maya for Catmull-Clark surfaces but never published.". We should all feel excited because we can save a lot of time to implement the same funcions in studio with current tools which we can easily receive, the Maya, our magic box.

stamboundary-1 stamboundary-2 

   Have you see the fur on the surface ? They are from the paper I mentioned above. The Disney Studio use this to plant the fur on subdivide surface in Maya modelling environment. If we only have the control polygon mesh we will not know what's the distribution the of the fur and  on subdivided mesh, how to control  the density is impossible too. Here is the snapshot of my Maya plugin, subdivide a polygon mesh into subdivided polygon mesh, it's huge, but easily to understand and modify.

Maya.Polygon RMCheck

  The left picture shows that what does linear interpolation do on UV set, the right shows that when we force RenderMan to use linear interpolatin instead of boundary interprolation. You can see the model I manually generated is the same as the RenderMan did.

   Here is the fur on the subdivide surface in Maya. It's nice and cool, could compare beauty with the same result from Utah University and Disney Studio, I thought.

 

Here is my Maya plugin to process a polygon mesh, it's very easily to extent to support the detection of boundary.

 

/*  *************************************************

Copyright (c) Bo Schwarzstein

Nanjing Adia Digtial Art Co,LTD
40 Nanchang Road, 6th Floor, Room 6008, Jiangsu, PRC

 Mail : Bo(dot)Schwarzstein(at)gmail.com
 Site : 
http://jedimaster.cnblogs.com
Phone : +86 13451813691

************************************************* 
*/

#include 
< maya / MFnPlugin.h >
#include 
< maya / MStatus.h >
#include 
< maya / MPxCommand.h >
#include 
< maya / MMessage.h >
#include 
< maya / MFnMesh.h >
#include 
< maya / MPointArray.h >
#include 
< maya / MFnSubd.h >
#include 
< maya / MItDag.h >
#include 
< maya / MGlobal.h >
#include 
< maya / MFloatArray.h >
#include 
< maya / MDagPath.h >
#include 
< maya / MArgList.h >
#include 
< maya / MSelectionList.h >
#include 
< maya / MUint64Array.h >
#include 
< maya / MItSubdFace.h >
#include 
< maya / MFnSubdData.h >
#include 
< maya / MDGModifier.h >

class  SubdOutput :  public  MPxCommand
{
public :
    
virtual  MStatus doIt(  const  MArgList &  );
    
static   void   * creator();
    
static  MSyntax newSyntax();
};

MStatus SubdOutput::doIt(
const  MArgList  &  Arg)
{
    MSelectionList SeleList;
    MGlobal::getActiveSelectionList(SeleList);
    
if ( SeleList.length()  ==   0   ||  SeleList.length()  >   2  )
    {
        MGlobal::displayError(
" Must Select A Polygon Mesh " );
        
return  MStatus::kFailure;
    }

    MDagPath DP;
    SeleList.getDagPath(
0 ,DP);

    
if ( DP.childCount()  >   2  )
    {
        MGlobal::displayError(
" Must Only Owns One Child Polygon Mesh " );
        
return  MStatus::kFailure;
    }

    MStatus S 
=  MStatus::kFailure;

    MFnMesh Mesh(DP.child(
0 ), & S);
    
if ( S  !=  MStatus::kSuccess )
    {
        MGlobal::displayError(
" Must Be A Polygon Mesh " );
        
return  MStatus::kFailure;
    }


    MFnSubd Subd;
    MIntArray VC,VL;
    MPointArray PA;
    Mesh.getVertices(VC,VL);
    Mesh.getPoints(PA);
    MFloatArray UA,VA;
    
int  UVCount  =  Mesh.numUVs();
    Mesh.getUVs(UA,VA);
    MObject SubdXform 
=  Subd.createBaseMesh( false ,Mesh.numVertices(),Mesh.numPolygons(),PA,VC,VL);

    MItSubdFace SubdFaceItr(Subd.
object ());
    
for int  i = 0 ; i < Mesh.numPolygons()  &&   ! SubdFaceItr.isDone();  ++ i, SubdFaceItr.next())
    {
        MIntArray IA;
        Mesh.getPolygonVertices(i,IA);
        MDoubleArray UA,VA;
        MUint64Array U64A;
        
for ( unsigned j = 0 ; j < IA.length();  ++ j )
        {
            
float  u,v;
            Mesh.getPolygonUV(i,j,u,v);
            UA.append(u);
            VA.append(v);
        }
        MUint64 ID 
=  SubdFaceItr.index();
        Subd.polygonSetUseUVs( ID, 
true  );
        Subd.polygonSetVertexUVs( ID, UA, VA );
    }

    
/*
    TODO : Manually assign the subdivide level or accept from MGlobal::getActiveSelectionList ?
           And this level should be equal to mtorSubd's "Steps" parameter.
    
*/
    
// Subd.levelFullySubdivideTo(3);

    MObject TessSubd 
=  Subd.tesselate( true , 3 , 1 );

    MDGModifier DGM;
    DGM.deleteNode( Subd.
object () );
    DGM.doIt();

    
return  MStatus::kSuccess;
}

void *  SubdOutput::creator()
{
    
return   new  SubdOutput;
}

MStatus __declspec(dllexport) initializePlugin( MObject O )
{
    MFnPlugin FnPlugin(O,
" Bo Schwarzstein " , " 9.0 " );
    MStatus S 
=  FnPlugin.registerCommand( " SubdOutput " , SubdOutput::creator);
    
if ! S )
    {
        S.perror(
" Can't Register MayaSubdOutput " );
    }
    
return  S;
}

MStatus __declspec(dllexport) uninitializePlugin( MObject O )
{
    MFnPlugin FnPlug(O);
    MStatus S 
=  FnPlug.deregisterCommand( " SubdOutput " );
    
if ! S )
    {
        S.perror(
" Can't Deregister MayaSubdOutput " );
    }
    
return  S;
}

 

Attention:

Maya Is Autodesk's Maya, Not Alias, Not Mine.

RenderMan Is Pixar Studio's Maya, Not Mine.

转载于:https://www.cnblogs.com/Jedimaster/archive/2008/08/16/1269372.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值