- adding mayaViewer as another code sample

- more work on the glutViewr example
    - fixing some compiling / linking issues for osd
This commit is contained in:
Manuel Kraemer 2012-06-11 11:53:35 -07:00
parent c2f42fa239
commit f66c7e19c9
9 changed files with 979 additions and 8 deletions

View File

@ -56,3 +56,5 @@
#
add_subdirectory(glutViewer)
add_subdirectory(mayaViewer)

View File

@ -57,7 +57,6 @@
find_package(IlmBase REQUIRED)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(GLUT REQUIRED)
find_package(CUDA REQUIRED)
@ -94,6 +93,5 @@ target_link_libraries(glutViewer
${ILMBASE_LIBS_DIRECTORY}
${OPENGL_LIBRARY}
${GLUT_LIBRARIES}
${}
)

View File

@ -0,0 +1,140 @@
//
// Copyright (C) Pixar. All rights reserved.
//
// This license governs use of the accompanying software. If you
// use the software, you accept this license. If you do not accept
// the license, do not use the software.
//
// 1. Definitions
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S.
// copyright law. A "contribution" is the original software, or
// any additions or changes to the software.
// A "contributor" is any person or entity that distributes its
// contribution under this license.
// "Licensed patents" are a contributor's patent claims that read
// directly on its contribution.
//
// 2. Grant of Rights
// (A) Copyright Grant- Subject to the terms of this license,
// including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide,
// royalty-free copyright license to reproduce its contribution,
// prepare derivative works of its contribution, and distribute
// its contribution or any derivative works that you create.
// (B) Patent Grant- Subject to the terms of this license,
// including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide,
// royalty-free license under its licensed patents to make, have
// made, use, sell, offer for sale, import, and/or otherwise
// dispose of its contribution in the software or derivative works
// of the contribution in the software.
//
// 3. Conditions and Limitations
// (A) No Trademark License- This license does not grant you
// rights to use any contributor's name, logo, or trademarks.
// (B) If you bring a patent claim against any contributor over
// patents that you claim are infringed by the software, your
// patent license from such contributor to the software ends
// automatically.
// (C) If you distribute any portion of the software, you must
// retain all copyright, patent, trademark, and attribution
// notices that are present in the software.
// (D) If you distribute any portion of the software in source
// code form, you may do so only under this license by including a
// complete copy of this license with your distribution. If you
// distribute any portion of the software in compiled or object
// code form, you may only do so under a license that complies
// with this license.
// (E) The software is licensed "as-is." You bear the risk of
// using it. The contributors give no express warranties,
// guarantees or conditions. You may have additional consumer
// rights under your local laws which this license cannot change.
// To the extent permitted under your local laws, the contributors
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#ifndef OSD_CUDA_INIT_H
#define OSD_CUDA_INIT_H
// From "NVIDIA GPU Computing SDK 4.2/C/common/inc/cutil_inline_runtime.h":
// Beginning of GPU Architecture definitions
inline int _ConvertSMVer2Cores_local(int major, int minor)
{
// Defines for GPU Architecture types (using the SM version to determine the # of cores per SM
typedef struct {
int SM; // 0xMm (hexidecimal notation), M = SM Major version, and m = SM minor version
int Cores;
} sSMtoCores;
sSMtoCores nGpuArchCoresPerSM[] =
{ { 0x10, 8 }, // Tesla Generation (SM 1.0) G80 class
{ 0x11, 8 }, // Tesla Generation (SM 1.1) G8x class
{ 0x12, 8 }, // Tesla Generation (SM 1.2) G9x class
{ 0x13, 8 }, // Tesla Generation (SM 1.3) GT200 class
{ 0x20, 32 }, // Fermi Generation (SM 2.0) GF100 class
{ 0x21, 48 }, // Fermi Generation (SM 2.1) GF10x class
{ 0x30, 192}, // Fermi Generation (SM 3.0) GK10x class
{ -1, -1 }
};
int index = 0;
while (nGpuArchCoresPerSM[index].SM != -1) {
if (nGpuArchCoresPerSM[index].SM == ((major << 4) + minor) ) {
return nGpuArchCoresPerSM[index].Cores;
}
index++;
}
printf("MapSMtoCores undefined SMversion %d.%d!\n", major, minor);
return -1;
}
// end of GPU Architecture definitions
// This function returns the best GPU (with maximum GFLOPS)
inline int cutGetMaxGflopsDeviceId()
{
int current_device = 0, sm_per_multiproc = 0;
int max_compute_perf = 0, max_perf_device = 0;
int device_count = 0, best_SM_arch = 0;
cudaDeviceProp deviceProp;
cudaGetDeviceCount( &device_count );
// Find the best major SM Architecture GPU device
while ( current_device < device_count ) {
cudaGetDeviceProperties( &deviceProp, current_device );
if (deviceProp.major > 0 && deviceProp.major < 9999) {
best_SM_arch = std::max(best_SM_arch, deviceProp.major);
}
current_device++;
}
// Find the best CUDA capable GPU device
current_device = 0;
while( current_device < device_count ) {
cudaGetDeviceProperties( &deviceProp, current_device );
if (deviceProp.major == 9999 && deviceProp.minor == 9999) {
sm_per_multiproc = 1;
} else {
sm_per_multiproc = _ConvertSMVer2Cores_local(deviceProp.major, deviceProp.minor);
}
int compute_perf = deviceProp.multiProcessorCount * sm_per_multiproc * deviceProp.clockRate;
if( compute_perf > max_compute_perf ) {
// If we find GPU with SM major > 2, search only these
if ( best_SM_arch > 2 ) {
// If our device==dest_SM_arch, choose this, or else pass
if (deviceProp.major == best_SM_arch) {
max_compute_perf = compute_perf;
max_perf_device = current_device;
}
} else {
max_compute_perf = compute_perf;
max_perf_device = current_device;
}
}
++current_device;
}
return max_perf_device;
}
#endif //OSD_CUDA_INIT_H

View File

@ -55,11 +55,10 @@
// a particular purpose and non-infringement.
//
#include <GL/glew.h>
#if defined(__APPLE__)
#include <GLUT/glut.h>
#else
#include <GL/glew.h>
#include <GL/glut.h>
#endif
@ -77,7 +76,6 @@
#include <cuda_runtime_api.h>
#include <cuda_gl_interop.h>
#include "cudaInit.h"
#endif
#include <omp.h>

View File

@ -0,0 +1,140 @@
#
# Copyright (C) Pixar. All rights reserved.
#
# This license governs use of the accompanying software. If you
# use the software, you accept this license. If you do not accept
# the license, do not use the software.
#
# 1. Definitions
# The terms "reproduce," "reproduction," "derivative works," and
# "distribution" have the same meaning here as under U.S.
# copyright law. A "contribution" is the original software, or
# any additions or changes to the software.
# A "contributor" is any person or entity that distributes its
# contribution under this license.
# "Licensed patents" are a contributor's patent claims that read
# directly on its contribution.
#
# 2. Grant of Rights
# (A) Copyright Grant- Subject to the terms of this license,
# including the license conditions and limitations in section 3,
# each contributor grants you a non-exclusive, worldwide,
# royalty-free copyright license to reproduce its contribution,
# prepare derivative works of its contribution, and distribute
# its contribution or any derivative works that you create.
# (B) Patent Grant- Subject to the terms of this license,
# including the license conditions and limitations in section 3,
# each contributor grants you a non-exclusive, worldwide,
# royalty-free license under its licensed patents to make, have
# made, use, sell, offer for sale, import, and/or otherwise
# dispose of its contribution in the software or derivative works
# of the contribution in the software.
#
# 3. Conditions and Limitations
# (A) No Trademark License- This license does not grant you
# rights to use any contributor's name, logo, or trademarks.
# (B) If you bring a patent claim against any contributor over
# patents that you claim are infringed by the software, your
# patent license from such contributor to the software ends
# automatically.
# (C) If you distribute any portion of the software, you must
# retain all copyright, patent, trademark, and attribution
# notices that are present in the software.
# (D) If you distribute any portion of the software in source
# code form, you may do so only under this license by including a
# complete copy of this license with your distribution. If you
# distribute any portion of the software in compiled or object
# code form, you may only do so under a license that complies
# with this license.
# (E) The software is licensed "as-is." You bear the risk of
# using it. The contributors give no express warranties,
# guarantees or conditions. You may have additional consumer
# rights under your local laws which this license cannot change.
# To the extent permitted under your local laws, the contributors
# exclude the implied warranties of merchantability, fitness for
# a particular purpose and non-infringement.
#
set(MAYA_FIND_QUIETLY TRUE)
find_package(Maya)
if(NOT MAYA_FOUND)
message(WARNING
"Maya could not be found, so the OpenSubdiv Maya plugin will not "
"be available. If you do have Maya installed and see this message, "
"please add your Maya path to cmake/FindMaya.cmake or set it in "
"the MAYA_LOCATION environment variable."
)
return()
endif()
include_directories(
${PROJECT_SOURCE_DIR}/opensubdiv
${MAYA_INCLUDE_DIRS}
${ILMBASE_INCLUDE_DIR}
)
set(SOURCE_FILES
OpenSubdivDrawOverride.cpp
hbrUtil.cpp
)
set(HEADER_FILES
)
if(UNIX)
set(PLATFORM_COMPILE_FLAGS
-D_BOOL
-DREQUIRE_IOSTREAM
)
set(PLATFORM_LIBRARIES
)
set(PLATFORM_PLUGIN_EXTENSION
.so
)
set(PLATFORM_LINK_FLAGS
)
endif(UNIX)
if(WIN32)
set(PLATFORM_COMPILE_FLAGS
/D_AFXDLL
/DNT_PLUGIN
/DREQUIRE_IOSTREAM
)
set(PLATFORM_LIBRARIES
)
set(PLATFORM_PLUGIN_EXTENSION
.mll
)
set(PLATFORM_LINK_FLAGS
"/export:initializePlugin /export:uninitializePlugin"
)
endif(WIN32)
add_definitions(
${PLATFORM_COMPILE_FLAGS}
)
add_library(maya_plugin SHARED
${SOURCE_FILES}
${HEADER_FILES}
)
set_target_properties(maya_plugin
PROPERTIES
OUTPUT_NAME "mayaViewer"
SUFFIX ${PLATFORM_PLUGIN_EXTENSION}
LINK_FLAGS "${PLATFORM_LINK_FLAGS}"
)
target_link_libraries(maya_plugin
osd
${MAYA_Foundation_LIBRARY}
${MAYA_OpenMaya_LIBRARY}
${MAYA_OpenMayaRender_LIBRARY}
${MAYA_tbb_LIBRARY}
${PLATFORM_LIBRARIES}
GLEW
)

View File

@ -0,0 +1,537 @@
// Include this first to avoid winsock2.h problems on Windows:
#include <maya/MTypes.h>
#include <osd/cpuDispatcher.h>
#include <osd/mesh.h>
#include "hbrUtil.h"
#include <GL/glew.h>
// Maya API includes
#include <maya/MDagPath.h>
#include <maya/MFnPlugin.h>
#include <maya/MFnMesh.h>
#include <maya/MFloatPointArray.h>
#include <maya/MIntArray.h>
#include <maya/MUintArray.h>
#include <maya/MDoubleArray.h>
#include <maya/MItMeshPolygon.h>
#include <maya/MPxCommand.h>
#include <maya/MSyntax.h>
#include <maya/MArgDatabase.h>
// Viewport 2.0 includes
#include <maya/MDrawRegistry.h>
#include <maya/MPxDrawOverride.h>
#include <maya/MUserData.h>
#include <maya/MDrawContext.h>
#include <maya/MGlobal.h>
#include <maya/MSelectionList.h>
//---------------------------------------------------------------------------
template<class T> static int
FindAttribute( MFnDependencyNode &fnDN, const char *nm, T *val )
{
MStatus s;
MPlug p;
T ss;
p = fnDN.findPlug(nm, &s);
if(s != MS::kSuccess) return -1;
s = p.getValue(ss);
if( s != MS::kSuccess ) return -1;
*val = ss;
return 0;
}
//---------------------------------------------------------------------------
template<class T> static bool
CompareArray(const T &a, const T &b)
{
if(a.length() != b.length()) return false;
for(unsigned int i = 0; i < a.length(); ++i){
if(a[i] != b[i]) return false;
}
return true;
}
//---------------------------------------------------------------------------
class SubdivUserData : public MUserData
{
public:
SubdivUserData(bool loop);
virtual ~SubdivUserData();
void Populate(MObject mesh);
void UpdatePoints(MObject mesh);
int GetElementBuffer() const { return _index; }
int GetNumIndices() const { return _numIndices; }
int GetVertexBuffer() const { return _osdmesh->GetVertexBuffer(); }
int GetVaryingBuffer() const { return _osdmesh->GetVaryingBuffer(); }
int GetVertexStride() const { return _osdmesh->GetNumVertexElements()*sizeof(float); }
int GetVaryingStride() const { return _osdmesh->GetNumVaryingElements()*sizeof(float); }
int GetPrimType() const { return _loop ? GL_TRIANGLES : GL_QUADS; }
// XXX
bool fIsSelected;
private:
// topology cache
MIntArray _vertexList;
MUintArray _edgeIds, _vtxIds;
MDoubleArray _edgeCreaseData, _vtxCreaseData;
int _level;
int _interpBoundary;
bool _loop;
OpenSubdiv::OsdMesh *_osdmesh;
GLuint _index;
int _numIndices;
float _cachedTotal;
};
//---------------------------------------------------------------------------
class OpenSubdivDrawOverride : public MHWRender::MPxDrawOverride
{
public:
static MHWRender::MPxDrawOverride* Creator(const MObject& obj) {
return new OpenSubdivDrawOverride(obj);
}
virtual ~OpenSubdivDrawOverride();
virtual MBoundingBox boundingBox(
const MDagPath& objPath,
const MDagPath& cameraPath) const;
virtual MUserData* prepareForDraw(
const MDagPath& objPath,
const MDagPath& cameraPath,
MUserData* oldData);
static void draw(const MHWRender::MDrawContext& context, const MUserData* data);
static void setLoopSubdivision(bool loop) { _loop = loop; }
private:
OpenSubdivDrawOverride(const MObject& obj);
bool getSelectionStatus(const MDagPath& objPath) const;
static bool _loop;
};
bool OpenSubdivDrawOverride::_loop = false;
//---------------------------------------------------------------------------
SubdivUserData::SubdivUserData(bool loop) :
MUserData(false /*don't delete after draw */),
_loop(loop)
{
_osdmesh = new OpenSubdiv::OsdMesh(6 /*numVertexElements*/,
0 /*numVaryingElements*/ );
glGenBuffers(1, &_index);
}
SubdivUserData::~SubdivUserData()
{
delete _osdmesh;
glDeleteBuffers(1, &_index);
}
void
SubdivUserData::Populate(MObject mesh)
{
MStatus s;
MFnMesh meshFn(mesh);
MIntArray vertexCount, vertexList;
meshFn.getVertices(vertexCount, vertexList);
MUintArray edgeIds;
MDoubleArray edgeCreaseData;
meshFn.getCreaseEdges(edgeIds, edgeCreaseData);
MUintArray vtxIds;
MDoubleArray vtxCreaseData;
meshFn.getCreaseVertices(vtxIds, vtxCreaseData );
short level = 1;
FindAttribute(meshFn, "smoothLevel", &level);
if(level < 1) level = 1;
short interpBoundary = 0;
FindAttribute(meshFn, "boundaryRule", &interpBoundary);
if(CompareArray(_vertexList, vertexList) &&
CompareArray(_edgeIds, edgeIds) &&
CompareArray(_edgeCreaseData, edgeCreaseData) &&
CompareArray(_vtxIds, vtxIds) &&
CompareArray(_vtxCreaseData, vtxCreaseData) &&
_level == level &&
_interpBoundary == interpBoundary)
{
return;
}
// update topology
_vertexList = vertexList;
_edgeIds = edgeIds;
_edgeCreaseData = edgeCreaseData;
_vtxIds = vtxIds;
_vtxCreaseData = vtxCreaseData;
_level = level;
_interpBoundary = interpBoundary;
if(_loop){
MIntArray triangleCounts;
meshFn.getTriangles(triangleCounts, vertexList);
int numTriangles = vertexList.length()/3;
vertexCount.clear();
for(int i = 0; i < numTriangles; ++i){
vertexCount.append(3);
}
}
// XXX redundant copy... replace _vertexList with numIndices, etc
// create Osd mesh
std::vector<int> numIndices, faceIndices, edgeCreaseIndices, vtxCreaseIndices;
std::vector<float> edgeCreases, vtxCreases;
numIndices.resize(vertexCount.length());
faceIndices.resize(vertexList.length());
for(int i = 0; i < (int)vertexCount.length(); ++i) numIndices[i] = vertexCount[i];
for(int i = 0; i < (int)vertexList.length(); ++i) faceIndices[i] = vertexList[i];
vtxCreaseIndices.resize(vtxIds.length());
for(int i = 0; i < (int)vtxIds.length(); ++i) vtxCreaseIndices[i] = vtxIds[i];
vtxCreases.resize(vtxCreaseData.length());
for(int i = 0; i < (int)vtxCreaseData.length(); ++i) vtxCreases[i] = (float)vtxCreaseData[i];
edgeCreases.resize(edgeCreaseData.length());
for(int i = 0; i < (int)edgeCreaseData.length(); ++i) edgeCreases[i] = (float)edgeCreaseData[i];
// edge crease index is stored as pair of <face id> <edge localid> ...
int nEdgeIds = edgeIds.length();
edgeCreaseIndices.resize(nEdgeIds*2);
for(int i = 0; i < nEdgeIds; ++i){
int2 vertices;
if (meshFn.getEdgeVertices(edgeIds[i], vertices) != MS::kSuccess) {
s.perror("ERROR can't get creased edge vertices");
continue;
}
edgeCreaseIndices[i*2] = vertices[0];
edgeCreaseIndices[i*2+1] = vertices[1];
}
std::string kernel = "omp";
OpenSubdiv::OsdHbrMesh *hbrMesh = ConvertToHBR(meshFn.numVertices(), numIndices, faceIndices,
vtxCreaseIndices, vtxCreases,
std::vector<int>(), std::vector<float>(),
edgeCreaseIndices, edgeCreases,
interpBoundary, _loop);
_osdmesh->Create(hbrMesh, level, kernel);
delete hbrMesh;
// update element array buffer
const std::vector<int> indices = _osdmesh->GetFarMesh()->GetFaceVertices(level);
_numIndices = indices.size();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _index);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*_numIndices,
&(indices[0]), GL_STATIC_DRAW);
_cachedTotal = -1;
UpdatePoints(mesh);
}
void
SubdivUserData::UpdatePoints(MObject mesh)
{
// update coarse vertex array
MFnMesh meshFn(mesh);
MStatus status;
int nPoints = meshFn.numVertices();
const float *points = meshFn.getRawPoints(&status);
// XXX: looking for other good way to detect change
float total = 0;
for(int i = 0; i < 3*nPoints; ++i) total += points[i];
if(_cachedTotal == total) return;
_cachedTotal = total;
MFloatVectorArray normals;
meshFn.getVertexNormals(true, normals);
if (nPoints != normals.length()) return; // XXX: error
// Update vertex
std::vector<float> vertex;
vertex.resize(nPoints*6);
for(int i = 0; i < nPoints; ++i){
vertex[i*6+0] = points[i*3+0];
vertex[i*6+1] = points[i*3+1];
vertex[i*6+2] = points[i*3+2];
vertex[i*6+3] = normals[i].x;
vertex[i*6+4] = normals[i].y;
vertex[i*6+5] = normals[i].z;
}
_osdmesh->UpdatePoints(vertex);
/* XXX
float *varying = new float[_osdmesh.GetNumVaryingElements()];
_osdmesh.BeginUpdateCoarseVertexVarying();
for(int i = 0; i < nPoints; ++i){
varying[0] = normals[i].x;
varying[1] = normals[i].y;
varying[2] = normals[i].z;
_osdmesh.UpdateCoarseVertexVarying(i, varying);
}
_osdmesh.EndUpdateCoarseVertexVarying();
delete[] varying;
*/
// subdivide
_osdmesh->Subdivide();
}
//---------------------------------------------------------------------------
OpenSubdivDrawOverride::OpenSubdivDrawOverride(const MObject& obj)
: MHWRender::MPxDrawOverride(obj, OpenSubdivDrawOverride::draw)
{
}
OpenSubdivDrawOverride::~OpenSubdivDrawOverride()
{
}
bool OpenSubdivDrawOverride::getSelectionStatus(const MDagPath& objPath) const
{
// retrieve the selection status of the node
MStatus status;
MSelectionList selectedList;
status = MGlobal::getActiveSelectionList(selectedList);
if(!status)
return false;
MDagPath pathCopy = objPath;
do {
if(selectedList.hasItem(pathCopy)) return true;
status = pathCopy.pop();
} while(status);
return false;
}
MBoundingBox OpenSubdivDrawOverride::boundingBox(const MDagPath& objPath, const MDagPath& cameraPath) const
{
MPoint corner1( -1.0, -1.0, -1.0 );
MPoint corner2( 1.0, 1.0, 1.0);
return MBoundingBox(corner1, corner2);
}
MUserData* OpenSubdivDrawOverride::prepareForDraw(
const MDagPath& objPath,
const MDagPath& cameraPath,
MUserData* oldData)
{
SubdivUserData* data = dynamic_cast<SubdivUserData*>(oldData);
if (!data)
{
// data did not exist or was incorrect type, create new
// XXX by the way, who release this object?
bool loop = _loop;
data = new SubdivUserData(loop);
}
data->fIsSelected = getSelectionStatus(objPath);
data->Populate(objPath.node());
data->UpdatePoints(objPath.node());
return data;
}
void OpenSubdivDrawOverride::draw(const MHWRender::MDrawContext& context, const MUserData* data)
{
// get cached data
bool isSelected = false;
SubdivUserData* mesh = const_cast<SubdivUserData*>(dynamic_cast<const SubdivUserData*>(data));
if (mesh)
{
isSelected = mesh->fIsSelected;
}
// set colour
static const float colorData[] = {1.0f, 0.0f, 0.0f};
static const float selectedColorData[] = {0.0f, 1.0f, 0.0f};
if(isSelected)
glColor3fv(selectedColorData);
else
glColor3fv(colorData);
MStatus status;
// set world matrix
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
MMatrix transform =
context.getMatrix(MHWRender::MDrawContext::kWorldViewMtx, &status);
if (status)
{
glLoadMatrixd(transform.matrix[0]);
}
// set projection matrix
glMatrixMode(GL_PROJECTION);
glPushMatrix();
MMatrix projection =
context.getMatrix(MHWRender::MDrawContext::kProjectionMtx, &status);
if (status)
{
glLoadMatrixd(projection.matrix[0]);
}
const int displayStyle = context.getDisplayStyle();
glPushAttrib( GL_CURRENT_BIT );
glPushAttrib( GL_ENABLE_BIT);
if(displayStyle & MHWRender::MDrawContext::kGouraudShaded) {
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}else if(displayStyle & MHWRender::MDrawContext::kWireFrame){
glDisable(GL_LIGHTING);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
{
int vertexStride = mesh->GetVertexStride();
int varyingStride = mesh->GetVaryingStride();
//printf("Draw. stride = %d\n", stride);
glBindBuffer(GL_ARRAY_BUFFER, mesh->GetVertexBuffer());
glVertexPointer(3, GL_FLOAT, vertexStride, ((char*)(0)));
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, mesh->GetVertexBuffer());
glNormalPointer(GL_FLOAT, vertexStride, ((char*)(12)));
// glBindBuffer(GL_ARRAY_BUFFER, mesh->GetVaryingBuffer());
// glNormalPointer(GL_FLOAT, varyingStride, ((char*)(0)));
glEnableClientState(GL_NORMAL_ARRAY);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->GetElementBuffer());
glDrawElements(mesh->GetPrimType(), mesh->GetNumIndices(), GL_UNSIGNED_INT, NULL);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
glPopAttrib();
glPopAttrib();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glColor3f(1, 1, 1);
}
//---------------------------------------------------------------------------
// Control command
class OpenSubdivCommand : public MPxCommand
{
public:
virtual MStatus doIt(const MArgList &args);
static void *Creator();
};
void*
OpenSubdivCommand::Creator()
{
return new OpenSubdivCommand();
}
MStatus
OpenSubdivCommand::doIt(const MArgList &args)
{
MSyntax syntax;
syntax.addFlag("m", "method", MSyntax::kString);
MArgDatabase argDB(syntax, args);
if(argDB.isFlagSet("m")){
MString method;
argDB.getFlagArgument("m", 0, method);
if(method == "loop"){
OpenSubdivDrawOverride::setLoopSubdivision(true);
}else{
OpenSubdivDrawOverride::setLoopSubdivision(false);
}
}
return MS::kSuccess;
}
//---------------------------------------------------------------------------
// Plugin Registration
//---------------------------------------------------------------------------
MString drawDbClassification("drawdb/geometry/mesh");
MString drawRegistrantId("OpenSubdivDrawOverridePlugin");
MStatus initializePlugin( MObject obj )
{
#if defined(_WIN32) && defined(_DEBUG)
// Disable buffering for stdout and stderr when using debug versions
// of the C run-time library.
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
#endif
MStatus status;
MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");
status = MHWRender::MDrawRegistry::registerDrawOverrideCreator(
drawDbClassification,
drawRegistrantId,
OpenSubdivDrawOverride::Creator);
if (!status) {
status.perror("registerDrawOverrideCreator");
return status;
}
status = plugin.registerCommand("openSubdivControl", OpenSubdivCommand::Creator);
if (!status) {
status.perror("registerCommand");
return status;
}
glewInit();
//XXX:cleanup Need to register other kernel dispatchers.
OpenSubdiv::OsdCpuKernelDispatcher::Register();
return status;
}
MStatus uninitializePlugin( MObject obj)
{
MStatus status;
MFnPlugin plugin( obj );
status = MHWRender::MDrawRegistry::deregisterDrawOverrideCreator(
drawDbClassification,
drawRegistrantId);
if (!status) {
status.perror("deregisterDrawOverrideCreator");
return status;
}
status = plugin.deregisterCommand("openSubdivControl");
return status;
}

View File

@ -0,0 +1,136 @@
#include "hbrUtil.h"
#include <far/mesh.h>
#include <hbr/mesh.h>
#include <hbr/bilinear.h>
#include <hbr/loop.h>
#include <hbr/catmark.h>
#define OSD_ERROR printf // XXXX
OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
std::vector<int> const & numIndices,
std::vector<int> const & faceIndices,
std::vector<int> const & vtxCreaseIndices,
std::vector<float> const & vtxCreases,
std::vector<int> const & edgeCrease1Indices, // face index, local edge index
std::vector<float> const & edgeCreases1,
std::vector<int> const & edgeCrease2Indices, // 2 vertex indices (Maya friendly)
std::vector<float> const & edgeCreases2,
int interpBoundary, bool loop)
{
static HbrBilinearSubdivision<OpenSubdiv::OsdVertex> _bilinear;
static HbrLoopSubdivision<OpenSubdiv::OsdVertex> _loop;
static HbrCatmarkSubdivision<OpenSubdiv::OsdVertex> _catmark;
OpenSubdiv::OsdHbrMesh *hbrMesh;
if (loop)
hbrMesh = new OpenSubdiv::OsdHbrMesh(&_loop);
else
hbrMesh = new OpenSubdiv::OsdHbrMesh(&_catmark);
OpenSubdiv::OsdVertex v;
for(int i = 0; i < nVertices; ++i){
// create empty vertex : actual vertices will be initialized in UpdatePoints();
hbrMesh->NewVertex(i, v);
}
// get face indices
std::vector<int> vIndex;
int nFaces = (int)numIndices.size(), offset = 0;
for (int i = 0; i < nFaces; ++i) {
int numVertex = numIndices[i];
vIndex.resize(numVertex);
bool valid=true;
for (int j=0; j<numVertex; ++j) {
vIndex[j] = faceIndices[j + offset];
int vNextIndex = faceIndices[(j+1)%numVertex + offset];
// check for non-manifold face
OpenSubdiv::OsdHbrVertex * origin = hbrMesh->GetVertex( vIndex[j] );
OpenSubdiv::OsdHbrVertex * destination = hbrMesh->GetVertex( vNextIndex );
if (!origin || !destination) {
OSD_ERROR("ERROR : An edge was specified that connected a nonexistent vertex");
valid=false;
}
if (origin == destination) {
OSD_ERROR("ERROR : An edge was specified that connected a vertex to itself");
valid=false;
}
OpenSubdiv::OsdHbrHalfedge * opposite = destination->GetEdge(origin);
if (opposite && opposite->GetOpposite()) {
OSD_ERROR("ERROR : A non-manifold edge incident to more than 2 faces was found");
valid=false;
}
if (origin->GetEdge(destination)) {
OSD_ERROR("ERROR : An edge connecting two vertices was specified more than once. "
"It's likely that an incident face was flipped");
valid=false;
}
}
if ( valid )
hbrMesh->NewFace(numVertex, &(vIndex[0]), 0);
else
OSD_ERROR("Face %d will be ignored\n", i);
offset += numVertex;
}
// XXX: use hbr enum or redefine same enum in gsd
hbrMesh->SetInterpolateBoundaryMethod((OpenSubdiv::OsdHbrMesh::InterpolateBoundaryMethod)interpBoundary);
// set edge crease in two different indexing way
int nEdgeCreases = (int)edgeCreases1.size();
for (int i = 0; i < nEdgeCreases; ++i) {
if( edgeCreases1[i] <= 0. )
continue;
OpenSubdiv::OsdHbrHalfedge * e = hbrMesh->GetFace(edgeCrease1Indices[i*2])->GetEdge(edgeCrease1Indices[i*2+1]);
if (!e) {
OSD_ERROR("Can't find edge (face %d edge %d)\n", edgeCrease1Indices[i*2], edgeCrease1Indices[i*2+1]);
continue;
}
e->SetSharpness( (float)edgeCreases1[i] );
}
nEdgeCreases = (int)edgeCreases2.size();
for (int i = 0; i < nEdgeCreases; ++i) {
if( edgeCreases1[i] <= 0. )
continue;
OpenSubdiv::OsdHbrVertex * v0 = hbrMesh->GetVertex(edgeCrease2Indices[i*2]);
OpenSubdiv::OsdHbrVertex * v1 = hbrMesh->GetVertex(edgeCrease2Indices[i*2+1]);
OpenSubdiv::OsdHbrHalfedge * e = NULL;
if ( v0 && v1 )
if ( ! (e = v0->GetEdge(v1)) )
e = v1->GetEdge(v0);
if (!e) {
OSD_ERROR("ERROR can't find edge");
continue;
}
e->SetSharpness( (float)edgeCreases2[i] );
}
// set corner
{
int nVertexCreases = (int)vtxCreases.size();
for ( int i = 0; i< nVertexCreases; ++i ) {
if( vtxCreases[i] <= 0. )
continue;
OpenSubdiv::OsdHbrVertex * v = hbrMesh->GetVertex(vtxCreaseIndices[i]);
if (!v) {
OSD_ERROR("Can't find vertex %d\n", vtxCreaseIndices[i]);
continue;
}
v->SetSharpness( (float)vtxCreases[i] );
}
}
hbrMesh->Finish();
return hbrMesh;
}

View File

@ -0,0 +1,18 @@
#ifndef OSD_HBR_UTIL_H
#define OSD_HBR_UTIL_H
#include <vector>
#include <osd/mesh.h>
extern "C" OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
std::vector<int> const & numIndices,
std::vector<int> const & faceIndices,
std::vector<int> const & vtxCreaseIndices,
std::vector<float> const & vtxCreases,
std::vector<int> const & edgeCrease1Indices,
std::vector<float> const & edgeCreases1,
std::vector<int> const & edgeCrease2Indices,
std::vector<float> const & edgeCreases2,
int interpBoundary,
bool loop);
#endif

View File

@ -100,10 +100,10 @@ set(PUBLIC_HEADERS
# CPU (omp) code & dependencies
if(APPLE)
set(PLATFORM_COMPILE_FLAGS
-fopenmp
-fopenmp
)
set(PLATFORM_LIBRARIES
gomp
gomp
)
elseif(UNIX)
set(PLATFORM_COMPILE_FLAGS
@ -119,7 +119,9 @@ elseif(WIN32 or WIN64)
)
endif()
add_definitions(
${PLATFORM_COMPILE_FLAGS}
)
#-------------------------------------------------------------------------------
# GL code & dependencies