filipkunc/MeshMaker

Reduce modifcations to OpenSubdiv?

Closed this issue · 2 comments

MeshMaker is a nice project, after a bit of simple messing around I got it to build and run.

I created the file below to reduce the need to modify a clean pull of OpenSubdiv. It's still necessary to add the two accessors (GetFarMesh and GetVertexBuffer) to osd/mesh.h, but having OsdMeshMaker.h as a file in MeshMaker/Classes makes life easier. Maybe the two accessors could be submitted to OpenSubdiv as a pull request, and this OsdMeshMaker.h file could be added to MeshMaker?


//
// OsdMeshMaker.h
// MeshMaker
//
//

pragma once

include <common/shape_utils.h>

class MeshMakerDrawContext : public OpenSubdiv::OsdDrawContext {
public:
typedef GLuint VertexBufferBinding;

MeshMakerDrawContext() { }
virtual ~MeshMakerDrawContext() { }

template<class VERTEX_BUFFER>
static MeshMakerDrawContext *Create(OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex> *farMesh,
                                    VERTEX_BUFFER *vertexBuffer,
                                    bool requirePtexCoordinates=false,
                                    bool requireFVarData=false) {
    if (not vertexBuffer)
        return NULL;

    MeshMakerDrawContext *instance = new MeshMakerDrawContext();
    return instance;
}

};

template void
createVertices(OpenSubdiv::HbrMesh *mesh, const std::vector &verts)
{
int vertexCount = verts.size() / 3;

T v;
for (int i = 0; i < vertexCount; i++)
    mesh->NewVertex(i, v);

}

template void
createTopology(OpenSubdiv::HbrMesh * mesh, const std::vector &faceverts, const std::vector &nvertsPerFace, Scheme scheme)
{
const int * fv=&(faceverts[0]);
for(int f=0, ptxidx=0;f<(int)nvertsPerFace.size(); f++ ) {
int nv = nvertsPerFace[f];

    if ((scheme==kLoop) and (nv!=3)) {
        printf("Trying to create a Loop surbd with non-triangle face\n");
        exit(1);
    }

    for(int j=0;j<nv;j++) {
        OpenSubdiv::HbrVertex<T> * origin      = mesh->GetVertex( fv[j] );
        OpenSubdiv::HbrVertex<T> * destination = mesh->GetVertex( fv[ (j+1)%nv] );
        OpenSubdiv::HbrHalfedge<T> * opposite  = destination->GetEdge(origin);

        if(origin==NULL || destination==NULL) {
            printf(" An edge was specified that connected a nonexistent vertex\n");
            exit(1);
        }

        if(origin == destination) {
            printf(" An edge was specified that connected a vertex to itself\n");
            exit(1);
        }

        if(opposite && opposite->GetOpposite() ) {
            printf(" A non-manifold edge incident to more than 2 faces was found\n");
            exit(1);
        }

        if(origin->GetEdge(destination)) {
            printf(" An edge connecting two vertices was specified more than once."
                   " It's likely that an incident face was flipped\n");

            exit(1);
        }
    }

    OpenSubdiv::HbrFace<T> * face = mesh->NewFace(nv, (int *)fv, 0);

    face->SetPtexIndex(ptxidx);

    if ( (scheme==kCatmark or scheme==kBilinear) and nv != 4 )
        ptxidx+=nv;
    else
        ptxidx++;

    fv+=nv;
}
mesh->SetInterpolateBoundaryMethod( OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryEdgeOnly );

//applyTags<T>( mesh, sh );
mesh->Finish();

}

template OpenSubdiv::HbrMesh *
simpleHbr2(const std::vector &vertices, const std::vector &faceverts, const std::vector &nvertsPerFace,
Scheme scheme)
{
OpenSubdiv::HbrMesh *mesh = createMesh(scheme);
createVertices(mesh, vertices);
createTopology(mesh, faceverts, nvertsPerFace, scheme);
return mesh;
}

I just needed a quick hack to make CPU based Catmull-Clark subdivision and OpenSubdiv does it. I would like to remove my fork of OpenSubdiv with some additions and maybe do something more sophisticated. For example I don't use live GPU based subdivision which OpenSubdiv is all about.

I see. For what it's worth I think OpenSubdiv is a pretty good choice in that it implements quite a lot of the corner cases that are hard to get right.