aboutsummaryrefslogtreecommitdiff
path: root/mayaPlug/shaveAPIimpl.cpp
diff options
context:
space:
mode:
authorBen Marsh <[email protected]>2019-10-22 09:07:59 -0400
committerBen Marsh <[email protected]>2019-10-22 09:07:59 -0400
commitbd0027e737c6512397f841c22786274ed74b927f (patch)
treef7ffbdb8f3741bb7f24635616cc189cba5cb865c /mayaPlug/shaveAPIimpl.cpp
downloadshave-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.cpp514
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];
+}