Created
February 5, 2013 20:48
Revisions
-
davidgyu created this gist
Feb 5, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,380 @@ // // This is a simple example that uses face-varying u,v data // with uniform catmull-clark subdivision using OpenSubdiv // // c++ -o displayOsdFVarCoord displayOsdFVarCoord.cpp -I$OPENSUBDIV/include -L$OPENSUBDIV/lib -losdCPU -lglut -lGL // #if defined(__APPLE__) #include <GLUT/glut.h> #else #include <stdlib.h> #include <GL/glew.h> #if defined(WIN32) #include <GL/wglew.h> #endif #include <GL/glut.h> #endif #include <osd/error.h> #include <osd/vertex.h> #include <far/mesh.h> #include <far/meshFactory.h> #include <hbr/mesh.h> #include <osd/cpuDispatcher.h> #include <osd/cpuVertexBuffer.h> #include <osd/cpuComputeContext.h> #include <osd/cpuComputeController.h> #include <iostream> #include <vector> std::vector<float> vertexBufferData; std::vector<int> indexBufferData; std::vector<float> uvBufferData; typedef OpenSubdiv::HbrMesh<OpenSubdiv::OsdVertex> OsdHbrMesh; typedef OpenSubdiv::HbrVertex<OpenSubdiv::OsdVertex> OsdHbrVertex; typedef OpenSubdiv::HbrFace<OpenSubdiv::OsdVertex> OsdHbrFace; typedef OpenSubdiv::HbrHalfedge<OpenSubdiv::OsdVertex> OsdHbrHalfedge; typedef OpenSubdiv::HbrFVarData<OpenSubdiv::OsdVertex> OsdHbrFVarData; typedef OpenSubdiv::FarMeshFactory<OpenSubdiv::OsdVertex> OsdFarMeshFactory; typedef OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex> OsdFarMesh; static OsdFarMesh * buildMesh(const float *vertexData, int numVertices, const int *indexData, int numIndices, const int *faceData, int numFaces, const float *uvData = NULL) { // Build HbrMesh to specify mesh topology static OpenSubdiv::HbrCatmarkSubdivision<OpenSubdiv::OsdVertex> _catmark; OsdHbrMesh *hbrMesh = NULL; if (uvData) { // This set of descriptors describes u,v per face vert static const int uvFVarCount = 2; static const int uvFVarIndices[] = { 0, 1 }; static const int uvFVarWidths[] = { 1, 1 }; static const int uvFVarTotalWidth = 2; hbrMesh = new OsdHbrMesh(&_catmark, uvFVarCount, uvFVarIndices, uvFVarWidths, uvFVarTotalWidth); } else { hbrMesh = new OsdHbrMesh(&_catmark); } // This example has boundary edges. hbrMesh->SetInterpolateBoundaryMethod( OsdHbrMesh::k_InterpolateBoundaryEdgeAndCorner); OpenSubdiv::OsdVertex v; for (int i = 0; i < numVertices; ++i) { hbrMesh->NewVertex(i, v); } std::vector<int> faceVerts; int faceDataOffset = 0; int ptexFaceIndex = 0; for (int fi = 0; fi<numFaces; ++fi) { int numFaceVerts = faceData[fi]; bool valid = true; faceVerts.resize(numFaceVerts); for (int fvi = 0; fvi < numFaceVerts; ++fvi) { int v0 = indexData[fvi + faceDataOffset]; int v1 = indexData[((fvi+1) % numFaceVerts) + faceDataOffset]; faceVerts[fvi] = v0; OsdHbrVertex * origin = hbrMesh->GetVertex(v0); OsdHbrVertex * destination = hbrMesh->GetVertex(v1); if (!origin || !destination) { std::cerr << "topology error: non-existent vertex\n"; valid = false; } if (origin == destination) { std::cerr << "topology error: vertex connected to itself\n"; valid = false; } OsdHbrHalfedge * opposite = destination->GetEdge(origin); if (opposite && opposite->GetOpposite()) { std::cerr << "topology error: non-manifold edge\n"; valid = false; } if (origin->GetEdge(destination)) { std::cerr << "topology error: duplicate edge\n"; valid = false; } } if (valid) { OsdHbrFace *face = hbrMesh->NewFace(numFaceVerts, &faceVerts[0], 0); face->SetPtexIndex(ptexFaceIndex); ptexFaceIndex += (numFaceVerts == 4) ? 1 : numFaceVerts; if (uvData) { int fvarWidth = hbrMesh->GetTotalFVarWidth(); const float *fvarFaceData = &uvData[faceDataOffset*fvarWidth]; for(int fvi=0; fvi<numFaceVerts; ++fvi) { OsdHbrVertex *v = hbrMesh->GetVertex( faceVerts[fvi] ); OsdHbrFVarData& fvarData = v->GetFVarData(face); if ( ! fvarData.IsInitialized() ) { fvarData.SetAllData(fvarWidth, fvarFaceData); } else if (!fvarData.CompareAll(fvarWidth, fvarFaceData)) { OsdHbrFVarData& fvarData = v->NewFVarData(face); fvarData.SetAllData(fvarWidth, fvarFaceData); } fvarFaceData += fvarWidth; } } } faceDataOffset += numFaceVerts; } hbrMesh->Finish(); int level = 1; OsdFarMeshFactory meshFactory(hbrMesh, level, false /*uniform*/); OsdFarMesh * farMesh = meshFactory.Create(true /*ptex*/, true /*fvar*/); delete hbrMesh; std::cerr << "==== vertices ====\n"; OpenSubdiv::OsdCpuComputeContext * computeContext = OpenSubdiv::OsdCpuComputeContext::Create(farMesh); OpenSubdiv::OsdCpuComputeController * computeController = new OpenSubdiv::OsdCpuComputeController(); OpenSubdiv::OsdCpuVertexBuffer * vertexBuffer = OpenSubdiv::OsdCpuVertexBuffer::Create(3, farMesh->GetNumVertices()); vertexBuffer->UpdateData(vertexData, numVertices); computeController->Refine(computeContext, vertexBuffer); const float *vbuffer = vertexBuffer->BindCpuBuffer(); vertexBufferData.assign(vbuffer, vbuffer+vertexBuffer->GetNumVertices() * vertexBuffer->GetNumElements()); for (int i=0; i<vertexBuffer->GetNumVertices(); ++i) { std::cerr << "(" << vbuffer[i*3+0] << ", " << vbuffer[i*3+1] << ", " << vbuffer[i*3+2] << ")\n"; } std::cerr << "==== indices ====\n"; const std::vector<int> &ibuffer = farMesh->GetFaceVertices(level); indexBufferData = ibuffer; for (int i=0; i<ibuffer.size(); i+=4) { std::cerr << "[" << ibuffer[i+0] << " " << ibuffer[i+1] << " " << ibuffer[i+2] << " " << ibuffer[i+3] << "]\n"; } std::cerr << "==== ptex coords data ====\n"; std::vector<int> const & ptexCoords = farMesh->GetPtexCoordinates(level); for (int i=0; i<ptexCoords.size(); i+=2) { const int *p = &ptexCoords[i]; int faceIndex = i / 2; int ptexFaceIndex = p[0]; int u = (p[1] >> 16) & 0xffff; int v = (p[1] & 0xffff); std::cerr << faceIndex << ": "; std::cerr << " ptex face: " << ptexFaceIndex; std::cerr << " uvoffset: (" << (float)u/(1<<level) << ", " << (float)v/(1<<level) << ")"; if (faceIndex < 0) { std::cerr << " non-quad coarse face"; } std::cerr << "\n"; } std::cerr << "==== fvar coords data ====\n"; if (uvData) { std::vector<float> const & fvarCoords = farMesh->GetFVarData(level); uvBufferData = fvarCoords; for (int i=0; i<fvarCoords.size(); i+=4*2) { const float *uv = &fvarCoords[i]; int faceIndex = i / (4*2); std::cerr << faceIndex << ":"; std::cerr << " (" << uv[0*2+0] << "," << uv[0*2+1] << ")"; std::cerr << " (" << uv[1*2+0] << "," << uv[1*2+1] << ")"; std::cerr << " (" << uv[2*2+0] << "," << uv[2*2+1] << ")"; std::cerr << " (" << uv[3*2+0] << "," << uv[3*2+1] << ")"; std::cerr << "\n"; } } return farMesh; } static void buildCylinder() { float vertexData[] = { 1.0,-1.0,-1.0, 1.0, 1.0,-1.0, -1.0,-1.0,-1.0, -1.0, 1.0,-1.0, -1.0,-1.0, 1.0, -1.0, 1.0, 1.0, 1.0,-1.0, 1.0, 1.0, 1.0, 1.0, }; int numVertices = (sizeof(vertexData) / sizeof(vertexData[0])) / 3; int indexData[] = { 0, 1, 3, 2, 2, 3, 5, 4, 4, 5, 7, 6, 6, 7, 1, 0, }; int numIndices = sizeof(indexData) / sizeof(indexData[0]); int faceData[] = { 4, 4, 4, 4, }; int numFaces = sizeof(faceData) / sizeof(faceData[0]); float uvData[] = { 0.0,0.0, 0.0,1.0, 0.25,1.0, 0.25,0.0, 0.25,0.0, 0.25,1.0, 0.5,1.0, 0.5,0.0, 0.5,0.0, 0.5,1.0, 0.75,1.0, 0.75,0.0, 0.75,0.0, 0.75,1.0, 1.0,1.0, 1.0,0.0, }; buildMesh(vertexData, numVertices, indexData, numIndices, faceData, numFaces, uvData); } int vpWidth = 512, vpHeight = 512; bool pressed = false; int prevX = 0, prevY = 0; float rotX = 0, rotY = 0; void reshape(int width, int height) { vpWidth = width; vpHeight = height; glutPostRedisplay(); } void display() { glClearColor(0.1, 0.1, 0.1, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glViewport(0, 0, vpWidth, vpHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1, 1, -1, 1, 1, 10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, -3); glRotatef(rotX, 1, 0, 0); glRotatef(rotY, 0, 1, 0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glBegin(GL_QUADS); int numQuads = indexBufferData.size() / 4; for (int face=0; face<numQuads; ++face) { for (int vert=0; vert<4; ++vert) { const float *uv0 = &uvBufferData[(face*4+vert)*2]; glColor3f(uv0[0], uv0[1], 0.0); glVertex3fv(&vertexBufferData[indexBufferData[face*4+vert]*3]); } } glEnd(); glutSwapBuffers(); } void mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON and state == GLUT_DOWN) { pressed = true; prevX = x; prevY = y; } else if (button == GLUT_LEFT_BUTTON and state == GLUT_UP) { pressed = false; } } void motion(int x, int y) { if (pressed) { rotX += float(y - prevY) / vpHeight * 360.0f; rotY += float(x - prevX) / vpHeight * 360.0f; prevX = x; prevY = y; } glutPostRedisplay(); } void keyboard(unsigned char key, int, int) { switch (key) { case 27: case 'q': exit(1); default: break; } } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); glutInitWindowSize(vpWidth, vpHeight); glutCreateWindow("Test"); buildCylinder(); glutReshapeFunc(reshape); glutDisplayFunc(display); glutMouseFunc(mouse); glutMotionFunc(motion); glutKeyboardFunc(keyboard); glutMainLoop(); }