diff options
| author | Ben Marsh <[email protected]> | 2019-10-22 09:07:59 -0400 |
|---|---|---|
| committer | Ben Marsh <[email protected]> | 2019-10-22 09:07:59 -0400 |
| commit | bd0027e737c6512397f841c22786274ed74b927f (patch) | |
| tree | f7ffbdb8f3741bb7f24635616cc189cba5cb865c /mayaPlug/shaveAPIimpl.cpp | |
| download | shave-and-a-haircut-bd0027e737c6512397f841c22786274ed74b927f.tar.xz shave-and-a-haircut-bd0027e737c6512397f841c22786274ed74b927f.zip | |
Adding Shave-and-a-Haircut 9.6
Diffstat (limited to 'mayaPlug/shaveAPIimpl.cpp')
| -rw-r--r-- | mayaPlug/shaveAPIimpl.cpp | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/mayaPlug/shaveAPIimpl.cpp b/mayaPlug/shaveAPIimpl.cpp new file mode 100644 index 0000000..d93dff9 --- /dev/null +++ b/mayaPlug/shaveAPIimpl.cpp @@ -0,0 +1,514 @@ +// Shave and a Haircut +// (c) 2019 Epic Games +// US Patent 6720962 + +#include <maya/MAngle.h> +#include <maya/MAnimControl.h> +#include <maya/MDagPath.h> +#include <maya/MFnCamera.h> +#include <maya/MFnDependencyNode.h> +#include <maya/MGlobal.h> +#include <maya/MObjectArray.h> +#include <maya/MSelectionList.h> +#include <maya/MTime.h> +#include <string.h> + +#include "shaveAPI.h" +#include "shaveAPIimpl.h" +#include "shaveCheckObjectVisibility.h" +#include "shaveConstant.h" +#include "shaveGlobals.h" +#include "shaveHairShape.h" +#include "shaveIO.h" +#include "shaveMaya.h" +#include "shaveRender.h" +#include "shaveRenderer.h" +#include "shaveSDK.h" +#include "shaveTextureStore.h" +#include "shaveUtil.h" + +#include <assert.h> + +std::vector<shaveHairShape*> shaveAPIimpl::mShaveNodes; + + +MStatus shaveAPIimpl::exportAllHair( + shaveAPI::HairInfo* hairInfo, bool renderableOnly +) +{ + MObjectArray shaveNodes; + + shaveRender::saveFrameGlobals(); + + if (renderableOnly) + { + shaveRenderer* renderer = shaveRender::getRenderer(); + + renderer->getRenderableShaveNodes(shaveNodes); + } + else + shaveUtil::getShaveNodes(shaveNodes); + + if (shaveNodes.length() == 0) return MS::kNotFound; + + return doExport(shaveNodes, hairInfo, shaveRender::getFrameGlobals()); +} + + +MStatus shaveAPIimpl::exportDRAFile(MString filename) +{ + MStatus st = MS::kSuccess; + + return st; +} + + +MStatus shaveAPIimpl::exportHair( + MObjectArray& shaveNodes, shaveAPI::HairInfo* hairInfo +) +{ + ////////// + //MGlobal::displayInfo(MString("shaveAPIimpl::exportHair number of nodes :") + shaveNodes.length()); + ///////// + + if (shaveNodes.length() < 1) return MS::kNotFound; + + unsigned int i; + + for (i = 0; i < shaveNodes.length(); i++) + { + MFnDependencyNode nodeFn(shaveNodes[i]); + + ////////////// + //MGlobal::displayInfo(MString("node: ") + nodeFn.name()); + ////////////// + + if (nodeFn.typeId() != shaveHairShape::id) return MS::kInvalidParameter; + } + + shaveRender::saveFrameGlobals(); + + MStatus stat = doExport(shaveNodes, hairInfo, shaveRender::getFrameGlobals()); +#ifdef _WIN32 + assert(_CrtCheckMemory()); +#endif + return stat; +} + + +MStatus shaveAPIimpl::exportOcclusions( + shaveAPI::SceneGeom* hairOcclusions, shaveAPI::SceneGeom* shadowOcclusions +) +{ + MStatus st; + + if ((hairOcclusions == NULL) && (shadowOcclusions == NULL)) + return MS::kSuccess; + + shaveRender::saveFrameGlobals(); + shaveMaya::getRenderGlobals(); + + freeSceneGeom(hairOcclusions); + freeSceneGeom(shadowOcclusions); + + shaveRender::SceneInfo* sceneInfo = shaveRender::getSceneInfo(); + + // + // If the caller only wants shadows and native illumination is on, then + // just return the empty list. + // + if ((hairOcclusions == NULL) && nativeIlluminationGlob) return MS::kSuccess; + + // + // If motion blur is on, get the shutter open and close times. If that + // fails for some reason, then treat it as it motion blur is off but + // return a status indicating what happened. + // + bool doMotionBlur = shaveMaya::doMotionBlur; + float shutterOpen = 0.0f; + float shutterClose = 0.0f; + + if (doMotionBlur) + { + st = shaveRender::getShutterTimes(shutterOpen, shutterClose); + + if (!st) doMotionBlur = false; + } + + if (doMotionBlur) + { + int i; + + shaveUtil::setFrame(shutterOpen); + shaveRender::buildOcclusionLists(shaveConstant::kShutterOpen); + + shaveUtil::setFrame(shutterClose); + shaveRender::buildOcclusionLists(shaveConstant::kShutterClose); + + // + // Calculate velocities. + // + if (hairOcclusions) + { + int numVerts = sceneInfo->shutterOpenCamScene.totalverts; + + if (sceneInfo->shutterCloseCamScene.totalverts < numVerts) + numVerts = sceneInfo->shutterCloseCamScene.totalverts; + + for (i = 0; i < numVerts; i++) + { + sceneInfo->shutterOpenCamScene.velocity[i].x = + sceneInfo->shutterCloseCamScene.v[i].x + - sceneInfo->shutterOpenCamScene.v[i].x; + + sceneInfo->shutterOpenCamScene.velocity[i].y = + sceneInfo->shutterCloseCamScene.v[i].y + - sceneInfo->shutterOpenCamScene.v[i].y; + + sceneInfo->shutterOpenCamScene.velocity[i].z = + sceneInfo->shutterCloseCamScene.v[i].z + - sceneInfo->shutterOpenCamScene.v[i].z; + } + } + + if (shadowOcclusions) + { + int numVerts = sceneInfo->shutterOpenShadowScene.totalverts; + + if (sceneInfo->shutterCloseShadowScene.totalverts < numVerts) + numVerts = sceneInfo->shutterCloseShadowScene.totalverts; + + for (i = 0; i < numVerts; i++) + { + sceneInfo->shutterOpenShadowScene.velocity[i].x = + sceneInfo->shutterCloseShadowScene.v[i].x + - sceneInfo->shutterOpenShadowScene.v[i].x; + + sceneInfo->shutterOpenShadowScene.velocity[i].y = + sceneInfo->shutterCloseShadowScene.v[i].y + - sceneInfo->shutterOpenShadowScene.v[i].y; + + sceneInfo->shutterOpenShadowScene.velocity[i].z = + sceneInfo->shutterCloseShadowScene.v[i].z + - sceneInfo->shutterOpenShadowScene.v[i].z; + } + } + } + else + shaveRender::buildOcclusionLists(shaveConstant::kShutterOpen); + + if (hairOcclusions) + copyWFTYPEToSceneGeom(hairOcclusions, sceneInfo->shutterOpenCamScene); + + if (shadowOcclusions) + { + copyWFTYPEToSceneGeom( + shadowOcclusions, sceneInfo->shutterOpenShadowScene + ); + } + + return st; +} + + +void shaveAPIimpl::freeHairInfo(shaveAPI::HairInfo* hairInfo) +{ + if (hairInfo) + { + SHAVEfree_hairtype((HAIRTYPE*)hairInfo); + SHAVEinit_hairtype((HAIRTYPE*)hairInfo); + } +} + + +void shaveAPIimpl::initHairInfo(shaveAPI::HairInfo* hairInfo) +{ + if (hairInfo) SHAVEinit_hairtype((HAIRTYPE*)hairInfo); +} + + +//****************************************** +// +// SceneGeom Interfaces +// +//****************************************** + + +void shaveAPIimpl::freeSceneGeom(shaveAPI::SceneGeom* sceneGeom) +{ + if (sceneGeom) + { + delete sceneGeom->faceVertices; + delete sceneGeom->faceStartIndices; + delete sceneGeom->faceEndIndices; + delete sceneGeom->vertices; + delete sceneGeom->velocities; + + initSceneGeom(sceneGeom); + } +} + + +void shaveAPIimpl::initSceneGeom(shaveAPI::SceneGeom* sceneGeom) +{ + if (sceneGeom) + { + sceneGeom->numVertices = 0; + sceneGeom->numFaces = 0; + sceneGeom->numFaceVertices = 0; + sceneGeom->faceVertices = NULL; + sceneGeom->faceStartIndices = NULL; + sceneGeom->faceEndIndices = NULL; + sceneGeom->vertices = NULL; + sceneGeom->velocities = NULL; + } +} + + +//****************************************** +// +// Utility Methods +// +//****************************************** + +void shaveAPIimpl::copyWFTYPEToSceneGeom( + shaveAPI::SceneGeom* sceneGeom, WFTYPE& wf +) +{ + // + // 'sceneGeom' MUST have been cleared before calling this method. + // + sceneGeom->numVertices = wf.totalverts; + sceneGeom->numFaces = wf.totalfaces; + sceneGeom->numFaceVertices = wf.totalfverts; + + if (wf.totalverts > 0) + { + // + // For performance, we *could* just move the ptrs from the WFTYPE + // over to the SceneGeom rather than allocating and copying. + // However, that would leave us mixing 'new' and 'malloc' memory + // allocations. We could handle that by adding a flag to SceneInfo + // to tell us where the memory came from, so that we know whether + // to 'delete' or 'free' it. But that's a bit messy, so for now + // we'll just copy the data. If performance becomes an issue then + // we can get fancy later. + // + sceneGeom->vertices = new shaveAPI::Vertex[wf.totalverts]; + sceneGeom->velocities = new shaveAPI::Vertex[wf.totalverts]; + + memcpy( + sceneGeom->vertices, wf.v, sizeof(shaveAPI::Vertex) * wf.totalverts + ); + + memcpy( + sceneGeom->velocities, + wf.velocity, + sizeof(shaveAPI::Vertex) * wf.totalverts + ); + } + + if (wf.totalfaces > 0) + { + sceneGeom->faceStartIndices = new int[wf.totalfaces]; + sceneGeom->faceEndIndices = new int[wf.totalfaces]; + + memcpy( + sceneGeom->faceStartIndices, + wf.face_start, + sizeof(int) * wf.totalfaces + ); + + memcpy( + sceneGeom->faceEndIndices, + wf.face_end, + sizeof(int) * wf.totalfaces + ); + } + + if (wf.totalfverts > 0) + { + sceneGeom->faceVertices = new int[wf.totalfverts]; + + memcpy( + sceneGeom->faceVertices, wf.facelist, sizeof(int) * wf.totalfverts + ); + } +} + + +MStatus shaveAPIimpl::clearHairStack() +{ + SHAVEclear_stack(); + mShaveNodes.clear(); + + return MS::kSuccess; +} + + +MStatus shaveAPIimpl::createHairStack( + MObjectArray& shaveNodes, const shaveGlobals::Globals& globals +) +{ + MStatus st; + MTime curTime = MAnimControl::currentTime(); + + clearHairStack(); + + SHAVEset_tile_limit( + (int)globals.tileMemoryLimit, (int)globals.transparencyDepth + ); + + // + // Save the shaveNode pointers. + // + unsigned int i; + + for (i = 0; i < shaveNodes.length(); i++) + { + MFnDependencyNode nodeFn(shaveNodes[i]); + + mShaveNodes.push_back((shaveHairShape*)nodeFn.userNode()); + } + + shaveMaya::getRenderGlobals(); + + if (shaveMaya::doMotionBlur) + { + float shutterOpen; + float shutterClose; + + st = shaveRender::getShutterTimes(shutterOpen, shutterClose); + + if (st) + { + // + // Do shutter open. + // + shaveUtil::setFrame(shutterOpen); +#ifdef PER_NODE_TEXLOOKUP + initTexInfoLookup2(shaveNodes, "", globals.verbose); +#else + initTexInfoLookup(shaveNodes, "", globals.verbose); +#endif + shaveRender::buildHairStack(shaveNodes, shaveConstant::kShutterOpen); + + // + // Do shutter close. + // + shaveUtil::setFrame(shutterClose); + shaveRender::buildHairStack(shaveNodes, shaveConstant::kShutterClose); + } + else + { + // + // We couldn't find a valid render camera, so go ahead and + // render without motion blur, but return a status code to let + // the caller know what happened. + // + st = MS::kUnknownParameter; +#ifdef PER_NODE_TEXLOOKUP + initTexInfoLookup2(shaveNodes, "", globals.verbose); +#else + initTexInfoLookup(shaveNodes, "", globals.verbose); +#endif + shaveRender::buildHairStack(shaveNodes, shaveConstant::kShutterBoth); + } + } + else + { + // + // No motion blur, so shutter open and close occur at the same + // time. + // +#ifdef PER_NODE_TEXLOOKUP + initTexInfoLookup2(shaveNodes, "", globals.verbose); +#else + initTexInfoLookup(shaveNodes, "", globals.verbose); +#endif + shaveRender::buildHairStack(shaveNodes, shaveConstant::kShutterBoth); + } + + return st; +} + + +MStatus shaveAPIimpl::doExport( + MObjectArray& shaveNodes, + shaveAPI::HairInfo* hairInfo, + const shaveGlobals::Globals& globals +) +{ +#ifdef _WIN32 + assert(_CrtCheckMemory()); +#endif + ////////// + //MGlobal::displayInfo(MString("shaveAPIimpl::doExport")); + ///////// + + MStatus st; + + SHAVEset_verbose(globals.verbose ? 1 : 0); + createHairStack(shaveNodes, globals); +#ifdef _WIN32 + assert(_CrtCheckMemory()); +#endif + if (st) + { + ////////// + //MGlobal::displayInfo(MString("stack created")); + ///////// + + freeHairInfo(hairInfo); +#ifdef _WIN32 + assert(_CrtCheckMemory()); +#endif + ////////// + //MGlobal::displayInfo(MString("freeHairInfo")); + ///////// + + int res = SHAVEexport_hairtype((HAIRTYPE*)hairInfo); +#ifdef _WIN32 + assert(_CrtCheckMemory()); +#endif +#ifdef _DEBUG + MGlobal::displayInfo(MString("SHAVEexport_hairtype result :") + res); + MGlobal::displayInfo(MString("hairInfo->numHairs :") + hairInfo->numHairs); + MGlobal::displayInfo(MString("hairInfo->numHairVertices :") + hairInfo->numHairVertices); + MGlobal::displayInfo(MString("hairInfo->numVertices :") + hairInfo->numVertices); +#endif + SHAVEclear_stack(); +#ifdef _WIN32 + assert(_CrtCheckMemory()); +#endif + ////////// + //MGlobal::displayInfo(MString("SHAVEclear_stack")); + ///////// + + if (shaveMaya::doMotionBlur) + { + ////////// + //MGlobal::displayInfo(MString("shaveUtil::setFrame")); + ///////// + + MTime curTime = MAnimControl::currentTime(); + + shaveUtil::setFrame((float)curTime.value()); + } + ////////// + //MGlobal::displayInfo(MString("done")); + ///////// + } +#ifdef _WIN32 + assert(_CrtCheckMemory()); +#endif + return st; +} + + +shaveHairShape* shaveAPIimpl::getNodeFromStack(unsigned int nodeIndex) +{ + if (nodeIndex >= mShaveNodes.size()) return NULL; + + return mShaveNodes[nodeIndex]; +} |