#include "gpuCacheShapeNode.h"
#include "gpuCacheStrings.h"
#include "gpuCacheConfig.h"
#include "gpuCacheRasterSelect.h"
#include "gpuCacheGLPickingSelect.h"
#include "gpuCacheUtil.h"
#include "gpuCacheSubSceneOverride.h"
#include "gpuCacheDrawTraversal.h"
#include "gpuCacheGLFT.h"
#include "gpuCacheUtil.h"
#include <maya/M3dView.h>
#include <maya/MAnimControl.h>
#include <maya/MDagPath.h>
#include <maya/MFnDagNode.h>
#include <maya/MDrawData.h>
#include <maya/MFileIO.h>
#include <maya/MFileObject.h>
#include <maya/MFnDagNode.h>
#include <maya/MMaterial.h>
#include <maya/MMatrix.h>
#include <maya/MSelectionList.h>
#include <maya/MSelectionMask.h>
#include <maya/MHWGeometryUtilities.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MGlobal.h>
#include <maya/MHardwareRenderer.h>
#include <maya/MViewport2Renderer.h>
#include <maya/MDagPathArray.h>
#include <maya/MDGMessage.h>
#include <maya/MEventMessage.h>
#include <maya/MModelMessage.h>
#include <maya/MUiMessage.h>
#include <maya/MItDag.h>
#include <maya/MFnCamera.h>
#include <maya/MFnSingleIndexedComponent.h>
#include <maya/MFnPluginData.h>
#include <maya/MMaterialArray.h>
#include <maya/MObjectArray.h>
#include <maya/MAttributeSpec.h>
#include <maya/MAttributeSpecArray.h>
#include <maya/MAttributeIndex.h>
#include <maya/MPxSurfaceShapeUI.h>
#include <maya/MPointArray.h>
#include <maya/MVectorArray.h>
#include <maya/MExternalContentInfoTable.h>
#include <maya/MExternalContentLocationTable.h>
#include <cassert>
#include <climits>
#include <tbb/parallel_reduce.h>
#include <tbb/blocked_range.h>
#define MCHECKERROR(STAT,MSG) \
if (!STAT) { \
perror(MSG); \
return MS::kFailure; \
}
#define MREPORTERROR(STAT,MSG) \
if (!STAT) { \
perror(MSG); \
}
#define MCHECKERRORVOID(STAT,MSG) \
if (!STAT) { \
perror(MSG); \
return; \
}
namespace {
using namespace GPUCache;
using namespace GPUCache::ShapeNodePrivate;
class DrawWireframeState : public DrawTraversalState
{
public:
DrawWireframeState(
const Frustum& frustrum,
const double seconds)
: DrawTraversalState(frustrum, seconds, kPruneNone)
{}
};
class DrawWireframeTraversal
: public DrawTraversal<DrawWireframeTraversal, DrawWireframeState>
{
public:
typedef DrawTraversal<DrawWireframeTraversal, DrawWireframeState> BaseClass;
DrawWireframeTraversal(
DrawWireframeState& state,
bool isReflection,
Frustum::ClippingResult parentClippingResult)
: BaseClass(state, xform, isReflection, parentClippingResult)
{}
void draw(const std::shared_ptr<const ShapeSample>& sample)
{
if (!sample->visibility()) return;
gGLFT->glLoadMatrixd(xform().matrix[0]);
if (sample->isBoundingBoxPlaceHolder()) {
state().vboProxy().drawBoundingBox(sample);
GlobalReaderCache::theCache().hintShapeReadOrder(subNode());
return;
}
assert(sample->positions());
assert(sample->normals());
state().vboProxy().drawWireframe(sample);
}
};
class DrawShadedTypes
{
public:
enum ColorType {
kSubNodeColor,
kDefaultColor,
kBlackColor,
kXrayColor
};
enum NormalsType {
kFrontNormals,
kBackNormals
};
};
class DrawShadedState : public DrawTraversalState, public DrawShadedTypes
{
public:
DrawShadedState(
const Frustum& frustrum,
const double seconds,
const TransparentPruneType transparentPrune,
const ColorType colorType,
const MColor& defaultDiffuseColor,
const NormalsType normalsType)
: DrawTraversalState(frustrum, seconds, transparentPrune),
fColorType(colorType),
fDefaultDiffuseColor(defaultDiffuseColor),
fNormalsType(normalsType)
{}
ColorType colorType() const { return fColorType; }
const MColor& defaultDiffuseColor()
const {
return fDefaultDiffuseColor; }
NormalsType normalsType() const { return fNormalsType; }
private:
const ColorType fColorType;
const MColor fDefaultDiffuseColor;
const NormalsType fNormalsType;
};
class DrawShadedTraversal
: public DrawTraversal<DrawShadedTraversal, DrawShadedState>,
public DrawShadedTypes
{
public:
typedef DrawTraversal<DrawShadedTraversal, DrawShadedState> BaseClass;
DrawShadedTraversal(
DrawShadedState& state,
bool isReflection,
Frustum::ClippingResult parentClippingResult)
: BaseClass(state, xform, isReflection, parentClippingResult)
{}
void draw(const std::shared_ptr<const ShapeSample>& sample)
{
if (!sample->visibility()) return;
gGLFT->glLoadMatrixd(xform().matrix[0]);
if (sample->isBoundingBoxPlaceHolder()) {
state().vboProxy().drawBoundingBox(sample, true);
GlobalReaderCache::theCache().hintShapeReadOrder(subNode());
return;
}
assert(sample->positions());
assert(sample->normals());
switch (state().colorType()) {
case kSubNodeColor:
diffuseColor = sample->diffuseColor();
break;
case kDefaultColor:
diffuseColor = state().defaultDiffuseColor();
break;
case kBlackColor:
diffuseColor =
MColor(0.0f, 0.0f, 0.0f, sample->diffuseColor()[3]);
break;
case kXrayColor:
diffuseColor =
MColor(sample->diffuseColor()[0],
sample->diffuseColor()[1],
sample->diffuseColor()[2],
0.3f);
break;
default:
assert(0);
break;
}
if (diffuseColor[3] <= 0.0 ||
(diffuseColor[3] >= 1.0 &&
state().transparentPrune() == DrawShadedState::kPruneOpaque) ||
(diffuseColor[3] < 1.0 &&
state().transparentPrune() == DrawShadedState::kPruneTransparent)) {
return;
}
gGLFT->glColor4f(diffuseColor[0]*diffuseColor[3],
diffuseColor[1]*diffuseColor[3],
diffuseColor[2]*diffuseColor[3],
diffuseColor[3]);
gGLFT->glFrontFace(isReflection() ? MGL_CW : MGL_CCW);
for (size_t groupId = 0; groupId < sample->numIndexGroups(); ++groupId ) {
state().vboProxy().drawTriangles(
sample, groupId,
state().normalsType() == kFrontNormals ?
VBOProxy::kFrontNormals : VBOProxy::kBackNormals,
VBOProxy::kNoUVs);
}
}
};
class ReadBufferVisitor : public SubNodeVisitor
{
public:
ReadBufferVisitor(
double seconds, BufferCache* buffer,
MMatrix xformMatrix)
: fSeconds(seconds), fMyBufferCache(buffer), fthisXForm(xformMatrix) {}
void visit(const XformData& xform,
const SubNode& subNode) override
{
const std::shared_ptr<const XformSample>& sample =
xform.getSample(fSeconds);
ReadBufferVisitor newVisitor(fSeconds, fMyBufferCache, sample->xform() * fthisXForm);
for(const SubNode::Ptr& child :
subNode.getChildren() ) {
child->accept(newVisitor);
}
}
void visit(const ShapeData& shape,
const SubNode& subNode) override
{
const std::shared_ptr<const ShapeSample>& sample =
shape.getSample(fSeconds);
if (!sample) return;
fMyBufferCache->fNumTriangles.push_back(sample->numTriangles());
fMyBufferCache->fNumEdges.push_back(sample->numWires());
fMyBufferCache->fTotalNumVerts+=sample->numVerts();
fMyBufferCache->fTotalNumTris+=sample->numTriangles();
VertexBuffer::ReadInterfacePtr vertexPositionRead= sample->positions()->readableInterface();
if (sample->triangleVertIndices(0) && sample->wireVertIndices()) {
fMyBufferCache->fPositions.push_back(vertexPositionRead);
IndexBuffer::ReadInterfacePtr triangleIndexRead = sample->triangleVertIndices(0)->readableInterface();
IndexBuffer::ReadInterfacePtr edgeIndexRead = sample->wireVertIndices()->readableInterface();
fMyBufferCache->fTriangleVertIndices.push_back(triangleIndexRead);
fMyBufferCache->fEdgeVertIndices.push_back(edgeIndexRead);
fMyBufferCache->fBoundingBoxes.push_back(sample->boundingBox());
fMyBufferCache->fXFormMatrix.push_back(fthisXForm);
fMyBufferCache->fXFormMatrixInverse.push_back(fthisXForm.inverse());
fMyBufferCache->fUseCachedBuffers = true;
fMyBufferCache->fNumShapes ++;
}
}
private:
BufferCache* fMyBufferCache;
double fSeconds;
};
class NbPrimitivesVisitor : public SubNodeVisitor
{
public:
NbPrimitivesVisitor(double seconds)
: fSeconds(seconds),
fNumWires(0),
fNumTriangles(0)
{}
size_t numWires() { return fNumWires; }
size_t numTriangles() { return fNumTriangles; }
void visit(const XformData& xform,
const SubNode& subNode) override
{
for(const SubNode::Ptr& child :
subNode.getChildren() ) {
child->accept(*this);
}
}
void visit(const ShapeData& shape,
const SubNode& subNode) override
{
const std::shared_ptr<const ShapeSample>& sample =
shape.getSample(fSeconds);
if (!sample) return;
fNumWires += sample->numWires();
fNumTriangles += sample->numTriangles();
}
private:
const double fSeconds;
size_t fNumWires;
size_t fNumTriangles;
};
class SnapTraversalState : public DrawTraversalState
{
public:
SnapTraversalState(const Frustum& frustrum,
const double seconds,
: DrawTraversalState(frustrum, seconds, kPruneNone),
fLocalToPort(localToPort),
fInclusiveMatrix(inclusiveMatrix),
fSnapInfo(snapInfo),
fSelected(false)
{}
const MMatrix& localToPort()
const {
return fLocalToPort; }
const MMatrix& inclusiveMatrix()
const {
return fInclusiveMatrix; }
bool selected() const { return fSelected; }
void setSelected() { fSelected = true; }
private:
bool fSelected;
};
class SnapTraversal
: public DrawTraversal<SnapTraversal, SnapTraversalState>
{
public:
typedef DrawTraversal<SnapTraversal, SnapTraversalState> BaseClass;
SnapTraversal(
SnapTraversalState& state,
bool isReflection,
Frustum::ClippingResult parentClippingResult)
: BaseClass(state, xform, false, parentClippingResult)
{}
void draw(const std::shared_ptr<const ShapeSample>& sample)
{
if (!sample->visibility()) return;
if (sample->isBoundingBoxPlaceHolder()) return;
assert(sample->positions());
VertexBuffer::ReadInterfacePtr readable = sample->positions()->readableInterface();
const float* const positions = readable->get();
unsigned int srx, sry, srw, srh;
state().snapInfo().selectRect(srx, sry, srw, srh);
double srxl = srx;
double sryl = sry;
double srxh = srx + srw;
double sryh = sry + srh;
const MMatrix localToPort = xform() * state().localToPort();
const MMatrix inclusiveMatrix = xform() * state().inclusiveMatrix();
size_t numVertices = sample->numVerts();
for (size_t vertexIndex=0; vertexIndex<numVertices; vertexIndex++)
{
const float* const currentPoint = &positions[vertexIndex*3];
MPoint loPt(currentPoint[0], currentPoint[1], currentPoint[2]);
MPoint pt = loPt * localToPort;
if (pt.
x >= srxl && pt.
x <= srxh &&
pt.
y >= sryl && pt.
y <= sryh &&
pt.
z >= 0.0 && pt.
z <= 1.0) {
MPoint wsPt = loPt * inclusiveMatrix;
state().snapInfo().setSnapPoint(wsPt);
state().setSelected();
}
}
}
};
class WaitCursor
{
public:
WaitCursor()
{
}
~WaitCursor()
{
}
private:
WaitCursor(const WaitCursor&);
const WaitCursor& operator=(const WaitCursor&);
};
}
namespace GPUCache {
const MTypeId ShapeNode::id(0x580000C4);
const MString ShapeNode::drawDbClassificationGeometry(
"drawdb/geometry/gpuCache" );
const MString ShapeNode::drawDbClassificationSubScene(
"drawdb/subscene/gpuCache" );
const MString ShapeNode::drawRegistrantId(
"gpuCache" );
MCallbackId ShapeNode::fsModelEditorChangedCallbackId;
const char* ShapeNode::nodeTypeName = "gpuCache";
const char* ShapeNode::selectionMaskName = "gpuCache";
static std::vector<MCallbackId> s3dViewPostRenderCallbackIds;
static std::vector<MCallbackId> s3dViewDeletedCallbackIds;
static int sNb3dViewPostRenderCallbacks = 0;
enum ModelEditorState {
kDefaultViewportOnly,
kViewport2Only,
kDefaultViewportAndViewport2
};
static ModelEditorState sModelEditorState = kDefaultViewportAndViewport2;
static void viewPostRender(
const MString &str,
void* )
{
VBOBuffer::nextRefresh();
}
static void clearPostRenderCallbacks()
{
{
std::vector<MCallbackId>::iterator it = s3dViewPostRenderCallbackIds.begin();
std::vector<MCallbackId>::iterator end = s3dViewPostRenderCallbackIds.end();
for (; it != end; ++it) {
}
s3dViewPostRenderCallbackIds.clear();
}
{
std::vector<MCallbackId>::iterator it = s3dViewDeletedCallbackIds.begin();
std::vector<MCallbackId>::iterator end = s3dViewDeletedCallbackIds.end();
for (; it != end; ++it) {
}
s3dViewDeletedCallbackIds.clear();
}
sNb3dViewPostRenderCallbacks = 0;
}
static void uiDeleted(void* clientData)
{
MUintPtrSz idx = reinterpret_cast<MUintPtrSz>(clientData);
s3dViewPostRenderCallbackIds[idx] = MCallbackId();
s3dViewDeletedCallbackIds[idx] = MCallbackId();
--sNb3dViewPostRenderCallbacks;
assert(sNb3dViewPostRenderCallbacks >= 0);
}
static void modelEditorChanged(void* )
{
static bool sVBOsClean = false;
static bool sViewport2BuffersClean = false;
bool hasDefaultViewport = false;
bool hasViewport2 = false;
for (unsigned int i = 0; i < viewCount; i++) {
hasDefaultViewport = true;
}
hasViewport2 = true;
}
}
if (hasDefaultViewport) {
sVBOsClean = false;
}
if (hasViewport2) {
sViewport2BuffersClean = false;
}
if (!hasDefaultViewport && !sVBOsClean) {
VBOBuffer::clear();
sVBOsClean = true;
}
if (!hasViewport2 && !sViewport2BuffersClean) {
SubSceneOverride::clear();
sViewport2BuffersClean = true;
}
if (hasDefaultViewport && hasViewport2) {
sModelEditorState = kDefaultViewportAndViewport2;
}
else if (hasDefaultViewport) {
sModelEditorState = kDefaultViewportOnly;
}
else if (hasViewport2) {
sModelEditorState = kViewport2Only;
}
else {
sModelEditorState = kDefaultViewportAndViewport2;
}
}
static void nodeAddedToModel(
MObject& node,
void* clientData)
{
ShapeNode* shapeNode = (ShapeNode*)dagNode.userNode();
assert(shapeNode);
if (!shapeNode) return;
shapeNode->addedToModelCB();
}
static void nodeRemovedFromModel(
MObject& node,
void* clientData)
{
ShapeNode* shapeNode = (ShapeNode*)dagNode.userNode();
assert(shapeNode);
if (!shapeNode) return;
shapeNode->removedFromModelCB();
}
static void TimeChangeCallback(
MTime& time,
void* clientData)
{
assert(clientData);
}
void* ShapeNode::creator()
{
return new ShapeNode;
}
{
aCacheFileName = typedAttrFn.
create(
"cacheFileName",
"cfn",
MCHECKERROR(stat, "MPxNode::addAttribute(aCacheFileName)");
aCacheGeomPath = typedAttrFn.
create(
"cacheGeomPath",
"cmp",
MCHECKERROR(stat, "MPxNode::addAttribute(aCacheFileName)");
if (Config::vp2OverrideAPI() != Config::kMPxDrawOverride) {
"modelEditorChanged", modelEditorChanged, NULL, &stat);
MCHECKERROR(stat, "MEventMessage::addEventCallback(modelEditorChanged)");
}
modelEditorChanged(NULL);
stat = DisplayPref::initCallback();
MCHECKERROR(stat, "DisplayPref::initCallbacks()");
return stat;
}
{
if (Config::vp2OverrideAPI() != Config::kMPxDrawOverride) {
}
DisplayPref::removeCallback();
clearPostRenderCallbacks();
assert( CacheFileRegistry::theCache().size() == 0 );
CacheFileRegistry::theCache().clear();
}
MStatus ShapeNode::init3dViewPostRenderCallbacks()
{
clearPostRenderCallbacks();
static MString listEditorPanelsCmd =
"gpuCacheListModelEditorPanels";
MCHECKERROR(exitStatus, "gpuCacheListModelEditorPanels");
sNb3dViewPostRenderCallbacks = editorPanels.
length();
for (int i=0; i<sNb3dViewPostRenderCallbacks; ++i) {
editorPanels[i], viewPostRender, NULL, &status);
MREPORTERROR(status, "MUiMessage::add3dViewPostRenderMsgCallback()");
s3dViewDeletedCallbackIds.push_back(MCallbackId());
s3dViewPostRenderCallbackIds.push_back(MCallbackId());
continue;
}
s3dViewPostRenderCallbackIds.push_back(callbackId);
editorPanels[i], uiDeleted, reinterpret_cast<void*>(MUintPtrSz(i)), &status);
MREPORTERROR(status, "MUiMessage::addUiDeletedCallback()");
s3dViewDeletedCallbackIds.push_back(MCallbackId());
continue;
}
s3dViewDeletedCallbackIds.push_back(callbackId);
}
}
}
return exitStatus;
}
ShapeNode::ShapeNode()
: fCachedGeometry()
, fCacheReadingState(kCacheReadingDone)
, fTimeChangeCallbackId(0)
{
fBufferCache = NULL;
}
ShapeNode::~ShapeNode()
{
while(!fSpatialSub.empty()){
delete fSpatialSub.back();
fSpatialSub.pop_back();
}
delete fBufferCache;
}
void ShapeNode::postConstructor()
{
setRenderable(true);
Config::initialize();
}
bool ShapeNode::isBounded() const
{
return true;
}
unsigned int ShapeNode::getIntersectionAccelerator(
const gpuCacheIsectAccelParams& accelParams,
double seconds
) const
{
if (!fCacheFileEntry || fCacheFileEntry->fReadState != CacheFileEntry::kReadingDone) {
return 0;
}
if( fBufferCache !=NULL && (fBufferCache->fUseCachedBuffers && fBufferCache->fBufferReadTime==seconds) && (!fSpatialSub.empty()) && (fSpatialSub[0]->matchesParams(accelParams)) )
{
return fSpatialSub.size();
}
else
{
while(!fSpatialSub.empty()){
delete fSpatialSub.back(); fSpatialSub.pop_back();
}
const SubNode::Ptr subNode = getCachedGeometry();
if(readBuffers(subNode,seconds)){
for(unsigned int s=0; s < fBufferCache->fNumShapes; s++){
const index_t* srcTriangleVertIndices = fBufferCache->fTriangleVertIndices[s]->get();
const float* srcPositions = fBufferCache->fPositions[s]->get();
fSpatialSub.push_back (new gpuCacheSpatialSubdivision(fBufferCache->fNumTriangles[s], srcTriangleVertIndices, srcPositions, fBufferCache->fBoundingBoxes[s], accelParams));
}
return fSpatialSub.size();
}
}
return 0;
}
bool ShapeNode::getEdgeSnapPoint(
const MPoint &rayPointSrc,
const MVector &rayDirectionSrc,
MPoint &theClosestPoint) {
gpuCacheIsectAccelParams accelParams = gpuCacheIsectAccelParams::autoUniformGridParams();
unsigned int numAccels = getIntersectionAccelerator(accelParams, seconds);
bool foundPoint = false;
if(numAccels > 0 && numAccels == fBufferCache->fNumShapes) {
unsigned int closestShape=0;
double minDist = std::numeric_limits<double>::max();
bool *checkedBox = new bool[fBufferCache->fNumShapes];
double *allDists = new double[fBufferCache->fNumShapes];
for(unsigned int s=0; s<fBufferCache->fNumShapes; s++){
checkedBox[s] = false;
if(fBufferCache->fNumTriangles[s]>0){
allDists[s] = gpuCacheIsectUtil::getEdgeSnapPointOnBox(rayPointSrc, rayDirectionSrc, xformBBox, closestPointOnBox);
if(allDists[s] < minDist){
minDist = allDists[s];
closestShape = s;
}
} else {
allDists[s] = std::numeric_limits<double>::max();
}
}
std::vector<int> potentialShapes;
for(unsigned int s=0; s<fBufferCache->fNumShapes; s++){
if(allDists[s]==minDist){
potentialShapes.push_back(s);
checkedBox[s]=true;
}
}
double coef_plane = rayDirectionSrc * rayPointSrc;
minDist = std::numeric_limits<double>::max();
while(!potentialShapes.empty()){
closestShape = potentialShapes.back();
potentialShapes.pop_back();
if(allDists[closestShape]<=minDist){
const index_t* srcTriangleVertIndices = fBufferCache->fTriangleVertIndices[closestShape]->get();
const float* srcPositions = fBufferCache->fPositions[closestShape]->get();
double dist = fSpatialSub[closestShape]->getEdgeSnapPoint(fBufferCache->fNumTriangles[closestShape], srcTriangleVertIndices, srcPositions,
rayPointSrc*fBufferCache->fXFormMatrixInverse[closestShape], rayDirectionSrc*fBufferCache->fXFormMatrixInverse[closestShape], clsPoint);
clsPoint *= fBufferCache->fXFormMatrix[closestShape];
double d = coef_plane - rayDirectionSrc * clsPoint;
MPoint projectedClsPoint = clsPoint + rayDirectionSrc * d;
dist = rayPointSrc.distanceTo(projectedClsPoint);
if(dist < minDist){
minDist = dist;
theClosestPoint = clsPoint;
foundPoint = true;
for(unsigned int s=0; s<fBufferCache->fNumShapes; s++){
if(!checkedBox[s] && allDists[s]<=minDist){
std::vector<int>::iterator it = potentialShapes.begin();
while (it != potentialShapes.end() && allDists[s]<allDists[*it])
{
it++;
}
potentialShapes.insert(it,s);
checkedBox[s]=true;
}
}
}
}
}
delete[] checkedBox;
delete[] allDists;
}
return foundPoint;
}
bool ShapeNode::closestPoint(
const MPoint &raySource,
const MVector &rayDirection,
MPoint &theClosestPoint,
MVector &theClosestNormal,
bool findClosestOnMiss,
double tolerance)
{
if(closestIntersectWithNorm(raySource,rayDirection,theClosestPoint,theClosestNormal)) {
return true;
} else if(findClosestOnMiss) {
if(getEdgeSnapPoint(raySource,rayDirection,theClosestPoint)) {
return true;
}
}
return false;
}
bool ShapeNode::canMakeLive() const {
return true;
}
bool ShapeNode::readBuffers(const SubNode::Ptr subNode, double seconds)const{
if(subNode == NULL) return false;
if(fBufferCache!=NULL && fBufferCache->fUseCachedBuffers && fBufferCache->fBufferReadTime==seconds) return true;
if(fBufferCache!=NULL){
delete fBufferCache;
}
fBufferCache = new BufferCache(seconds);
if(fBufferCache == NULL){
return false;
}
ReadBufferVisitor visitor(seconds, fBufferCache, identMat);
subNode->accept(visitor);
if(fBufferCache->fUseCachedBuffers && (fBufferCache->fNumShapes)>1 && (fBufferCache->fTotalNumTris) > 1000000){
}
return fBufferCache->fUseCachedBuffers;
}
void ShapeNode::closestPoint(
const MPoint &toThisPoint,
MPoint &theClosestPoint,
double tolerance) {
gpuCacheIsectAccelParams accelParams = gpuCacheIsectAccelParams::autoUniformGridParams();
unsigned int numAccels = getIntersectionAccelerator(accelParams, seconds);
if(numAccels > 0 && numAccels == fBufferCache->fNumShapes) {
unsigned int closestShape=0;
double minDist = std::numeric_limits<double>::max();
bool *checkedBox = new bool[fBufferCache->fNumShapes];
double *allDists = new double[fBufferCache->fNumShapes];
for(unsigned int s=0; s<fBufferCache->fNumShapes; s++){
checkedBox[s] = false;
if(fBufferCache->fNumTriangles[s]>0){
allDists[s] = gpuCacheIsectUtil::getClosestPointOnBox(toThisPoint,xformBBox,closestPointOnBox);
if(allDists[s] < minDist){
minDist = allDists[s];
closestShape = s;
}
} else {
allDists[s] = std::numeric_limits<double>::max();
}
}
std::vector<int> potentialShapes;
potentialShapes.push_back(closestShape);
minDist = std::numeric_limits<double>::max();
while(!potentialShapes.empty()){
closestShape = potentialShapes.back();
potentialShapes.pop_back();
checkedBox[closestShape]=true;
if(allDists[closestShape]<minDist){
const index_t* srcTriangleVertIndices = fBufferCache->fTriangleVertIndices[closestShape]->get();
const float* srcPositions = fBufferCache->fPositions[closestShape]->get();
fSpatialSub[closestShape]->closestPointToPoint(fBufferCache->fNumTriangles[closestShape], srcTriangleVertIndices, srcPositions, toThisPoint * fBufferCache->fXFormMatrixInverse[closestShape], clsPoint);
clsPoint *= fBufferCache->fXFormMatrix[closestShape];
if(dist < minDist){
minDist = dist;
theClosestPoint = clsPoint;
for(unsigned int s=0; s<fBufferCache->fNumShapes; s++){
if(!checkedBox[s] && allDists[s]<minDist){
std::vector<int>::iterator it = potentialShapes.begin();
while (it != potentialShapes.end() && allDists[s]<allDists[*it])
{
it++;
}
potentialShapes.insert(it,s);
}
}
}
}
}
delete[] checkedBox;
delete[] allDists;
}
}
gpuCacheIsectAccelParams accelParams = gpuCacheIsectAccelParams::autoUniformGridParams();
unsigned int numAccels = getIntersectionAccelerator(accelParams, seconds);
if(numAccels > 0 && numAccels == fBufferCache->fNumShapes) {
double minDist = std::numeric_limits<double>::max();
for(unsigned int s=0; s<fBufferCache->fNumShapes; s++){
const index_t* srcTriangleVertIndices = fBufferCache->fTriangleVertIndices[s]->get();
const float* srcPositions = fBufferCache->fPositions[s]->get();
if( fSpatialSub[s]->closestIntersection(fBufferCache->fNumTriangles[s], srcTriangleVertIndices, srcPositions, toThisPoint * fBufferCache->fXFormMatrixInverse[s], thisDirection * fBufferCache->fXFormMatrixInverse[s],
999999, clsPoint, clsNormal)){
clsPoint *= fBufferCache->fXFormMatrix[s];
clsNormal *= fBufferCache->fXFormMatrix[s];
if(dist < minDist){
minDist = dist;
theClosestPoint = clsPoint;
theClosestNormal = clsNormal;
}
}
}
}
return returnStatus;
}
{
const SubNode::Ptr subNode = getCachedGeometry();
if (!subNode) {
}
const SubNodeData::Ptr subNodeData = subNode->getData();
const XformData::Ptr xform =
std::dynamic_pointer_cast<const XformData>(subNodeData);
if (xform) {
const std::shared_ptr<const XformSample>& sample =
xform->getSample(seconds);
return sample->boundingBox();
}
const ShapeData::Ptr shape =
std::dynamic_pointer_cast<const ShapeData>(subNodeData);
if (shape) {
const std::shared_ptr<const ShapeSample>& sample =
shape->getSample(seconds);
return sample->boundingBox();
}
}
{
if (plug == aCacheFileName) {
return true;
}
else if (plug == aCacheGeomPath) {
return true;
}
}
bool ShapeNode::setInternalValues(
)
{
const MString oldFileName = fCacheFileName;
const MString oldResolvedFileName = fResolvedCacheFileName;
const MString oldGeomPath = fCacheGeomPath;
if( newResolvedFileName.
length() == 0 )
{
newResolvedFileName = newFileName;
}
bool fileChanged = (newFileName != oldFileName);
bool pathChanged = (newGeomPath != oldGeomPath);
if (!fileChanged && !pathChanged)
{
return true;
}
if( fileChanged )
{
if( newResolvedFileName.
length() > 0 )
{
CacheFileEntry::MPtr entry = CacheFileRegistry::theCache().find(newResolvedFileName);
if( entry )
{
fCachedGeometry.reset();
fCachedMaterial.reset();
fCacheFileName = newFileName;
fResolvedCacheFileName = newResolvedFileName;
fCacheGeomPath = newGeomPath;
fCacheFileEntry = entry;
fCacheReadingState = kCacheReadingFile;
CacheShapeRegistry::theCache().remove(oldResolvedFileName, thisMObject());
CacheShapeRegistry::theCache().insert(newResolvedFileName, thisMObject());
CacheFileRegistry::theCache().cleanUp(oldResolvedFileName);
return true;
}
}
fCacheFileName = newFileName;
fResolvedCacheFileName = newResolvedFileName;
fCacheGeomPath = newGeomPath;
CacheShapeRegistry::theCache().remove(oldResolvedFileName, thisMObject());
CacheShapeRegistry::theCache().insert(newResolvedFileName, thisMObject());
fCachedGeometry.reset();
fCachedMaterial.reset();
fCacheFileEntry.reset();
CacheFileRegistry::theCache().cleanUp(oldResolvedFileName);
if( newResolvedFileName.
length() > 0 )
{
CacheFileEntry::MPtr newEntry = CacheFileEntry::create( newResolvedFileName );
CacheFileRegistry::theCache().insert( newResolvedFileName, newEntry );
fCacheFileEntry = newEntry;
fCacheReadingState = kCacheReadingFile;
}
}
else
{
fCacheGeomPath = newGeomPath;
fCacheReadingState = kCacheReadingFile;
}
return true;
}
bool ShapeNode::setInternalValue(
const MPlug & plug,
const MDataHandle & handle)
{
if (plug == aCacheFileName) {
return setInternalValues(newFileName, fCacheGeomPath);
}
else if (plug == aCacheGeomPath) {
return setInternalValues(fCacheFileName, newGeomPath);
}
}
void ShapeNode::refreshCachedGeometry( bool clearFileCache )
{
const MString cacheFileName = fCacheFileName;
const MString resolvedCacheFileName = fResolvedCacheFileName;
const MString cacheGeomPath = fCacheGeomPath;
if (fCacheFileEntry && fCacheFileEntry->fReadState != CacheFileEntry::kReadingDone) {
GlobalReaderCache::theCache().cancelRead(fCacheFileEntry.get());
fCacheFileEntry->fReadState = CacheFileEntry::kReadingDone;
}
if (fCacheReadingState != kCacheReadingDone) {
fCacheReadingState = kCacheReadingDone;
}
if( clearFileCache )
{
CacheFileRegistry::theCache().remove(resolvedCacheFileName);
}
CacheShapeRegistry::theCache().remove(resolvedCacheFileName, thisMObject());
fResolvedCacheFileName.clear();
fCacheGeomPath.clear();
fCachedGeometry.reset();
fCachedMaterial.reset();
fCacheFileEntry.reset();
setInternalValues(cacheFileName, cacheGeomPath);
if( clearFileCache )
{
refreshOtherCachedShapes( resolvedCacheFileName );
}
}
void ShapeNode::refreshOtherCachedShapes(
const MString& cacheFileName )
{
{
return;
}
std::vector<MObjectHandle> otherShapes;
CacheShapeRegistry::theCache().find( cacheFileName, otherShapes );
for( size_t i = 0; i < otherShapes.size(); i++ )
{
if( !otherShapes[i].isValid() )
{
continue;
}
assert( nodeFn.
typeId() == id );
ShapeNode* shape = (ShapeNode*) nodeFn.
userNode();
assert( shape );
shape->refreshCachedGeometry( false );
}
}
const SubNode::Ptr& ShapeNode::getCachedGeometry() const
{
CacheFileEntry::MPtr entry = fCacheFileEntry;
assert(!(entry && entry->fCacheReaderProxy && (entry->fCachedGeometry || entry->fCachedMaterial)));
if( fCacheReadingState == kCacheReadingFile )
{
assert(entry);
if (fCacheFileEntry->fCacheReaderProxy) {
GlobalReaderCache::theCache().scheduleRead(entry.get(),
"|",
fCacheFileEntry->fCacheReaderProxy);
entry->fReadState = CacheFileEntry::kReadingHierarchyInProgress;
}
else {
WaitCursor waitCursor;
GlobalReaderCache::CacheReaderHolder holder(fCacheFileEntry->fCacheReaderProxy);
const std::shared_ptr<CacheReader> cacheReader = holder.getCacheReader();
if (cacheReader && cacheReader->valid()) {
entry->fCachedGeometry = cacheReader->readScene(
"|", !Config::isIgnoringUVs());
entry->fCachedMaterial = cacheReader->readMaterials();
}
}
fCacheFileEntry->fCacheReaderProxy.reset();
}
if (entry->fReadState == CacheFileEntry::kReadingHierarchyInProgress) {
if (GlobalReaderCache::theCache().pullHierarchy(entry.get(), entry->fCachedGeometry, validatedGeometryPath, entry->fCachedMaterial)) {
entry->fReadState = CacheFileEntry::kReadingShapesInProgress;
if (!entry->fCachedGeometry) {
entry->fReadState = CacheFileEntry::kReadingDone;
}
const_cast<ShapeNode*>(this)->childChanged(kBoundingBoxChanged);
}
}
else if (entry->fReadState == CacheFileEntry::kReadingShapesInProgress) {
if (GlobalReaderCache::theCache().pullShape(entry.get(), entry->fCachedGeometry)) {
entry->fReadState = CacheFileEntry::kReadingDone;
}
}
bool readingDone = (entry->fReadState == CacheFileEntry::kReadingDone);
bool readingHierarchyDone = readingDone || (entry->fReadState == CacheFileEntry::kReadingShapesInProgress);
if( readingHierarchyDone )
{
CreateSubNodeHierarchy(entry->fCachedGeometry, fCacheGeomPath, validatedGeomPath, fCachedGeometry);
fCachedMaterial = entry->fCachedMaterial;
updateGeomPath( validatedGeomPath );
}
if( readingDone )
{
fCacheReadingState = kCacheReadingDone;
}
}
return fCachedGeometry;
}
void ShapeNode::updateGeomPath(
const MString& validatedGeomPath )
const
{
if (fCacheGeomPath != validatedGeomPath) {
if (fCacheGeomPath.length() > 0) {
fCacheGeomPath, fCacheFileName, validatedGeomPath);
}
fCacheGeomPath = validatedGeomPath;
"evalDeferred \"autoUpdateAttrEd;\";");
}
}
const MaterialGraphMap::Ptr& ShapeNode::getCachedMaterial() const
{
getCachedGeometry();
return fCachedMaterial;
}
const CacheFileEntry::MPtr& ShapeNode::getCacheFileEntry() const
{
return fCacheFileEntry;
}
const CacheFileEntry::BackgroundReadingState ShapeNode::backgroundReadingState() const
{
if( fCacheFileEntry )
{
return fCacheFileEntry->fReadState;
}
return CacheFileEntry::kReadingDone;
}
bool shortName, bool unresolvedName, bool markCouldBeImageSequence ) const
{
if(unresolvedName)
{
}
else
{
}
return files;
}
void ShapeNode::copyInternalData(
MPxNode* source)
{
if (source && source->
typeId() == id) {
ShapeNode* node = dynamic_cast<ShapeNode*>(source);
fCacheFileName = node->fCacheFileName;
fCacheGeomPath = node->fCacheGeomPath;
fCachedGeometry = node->fCachedGeometry;
fCachedMaterial = node->fCachedMaterial;
fCacheFileEntry = node->fCacheFileEntry;
fCacheReadingState = kCacheReadingFile;
}
}
{
}
{
}
bool ShapeNode::excludeAsPluginShape() const
{
return false;
}
void ShapeNode::addedToModelCB()
{
CacheShapeRegistry::theCache().insert(fResolvedCacheFileName, thisMObject());
refreshCachedGeometry(false);
}
void ShapeNode::removedFromModelCB()
{
if (fTimeChangeCallbackId)
{
fTimeChangeCallbackId = 0;
}
CacheShapeRegistry::theCache().remove(fResolvedCacheFileName, thisMObject());
fCacheReadingState = kCacheReadingDone;
fCacheFileEntry.reset();
CacheFileRegistry::theCache().cleanUp(fResolvedCacheFileName);
}
void ShapeNode::timeChangeCB(double timeInSeconds)
{
fBoundingBox = boundingBox();
if (prevBoundingBox.
min() != fBoundingBox.min() ||
prevBoundingBox.
max() != fBoundingBox.max())
{
}
}
void ShapeNode::dirtyVP2Geometry(
const MString& fileName )
{
if( Config::vp2OverrideAPI() == Config::kMPxDrawOverride )
{
std::vector<MObjectHandle> shapes;
CacheShapeRegistry::theCache().find( fileName, shapes );
size_t nShapes = shapes.size();
for( size_t i = 0; i < nShapes; i++ )
{
if( !shapes[i].isValid() )
{
continue;
}
MObject shape = shapes[i].object();
}
}
}
CacheShapeRegistry CacheShapeRegistry::fsSingleton;
CacheShapeRegistry::Map CacheShapeRegistry::fMap;
CacheShapeRegistry::CacheShapeRegistry()
{}
CacheShapeRegistry::~CacheShapeRegistry()
{}
CacheShapeRegistry& CacheShapeRegistry::theCache()
{
return fsSingleton;
}
void CacheShapeRegistry::getAll( std::vector<MObjectHandle>& shapes )
{
shapes.clear();
for( Map::iterator it = fMap.begin(); it != fMap.end(); it++ )
{
shapes.push_back( it->second );
}
}
void CacheShapeRegistry::find(
const MString& key, std::vector<MObjectHandle>& shapes )
{
shapes.clear();
std::pair<Map::iterator, Map::iterator> its = fMap.equal_range(key);
for( Map::iterator it = its.first; it != its.second; it++ )
{
shapes.push_back(it->second);
}
}
{
Map::value_type item( key, shape );
fMap.insert( item );
return true;
}
{
std::pair<Map::iterator, Map::iterator> its = fMap.equal_range(key);
for( Map::iterator it = its.first; it != its.second; it++ )
{
if( it->first == key &&
it->second == shape )
{
fMap.erase(it);
return true;
}
}
return false;
}
void CacheShapeRegistry::clear()
{
fMap.clear();
}
DisplayPref::WireframeOnShadedMode DisplayPref::fsWireframeOnShadedMode;
MCallbackId DisplayPref::fsDisplayPrefChangedCallbackId;
MStatus DisplayPref::initCallback()
{
"DisplayPreferenceChanged", DisplayPref::displayPrefChanged, NULL, &stat);
MCHECKERROR(stat, "MEventMessage::addEventCallback(DisplayPreferenceChanged");
displayPrefChanged(NULL);
return MS::kSuccess;
}
MStatus DisplayPref::removeCallback()
{
MCHECKERROR(stat, "MEventMessage::removeCallback(DisplayPreferenceChanged)");
return MS::kSuccess;
}
void DisplayPref::displayPrefChanged(void*)
{
"displayPref -q -wireframeOnShadedActive", false, false, &stat);
if (stat) {
if (wireframeOnShadedActive == "full") {
fsWireframeOnShadedMode = kWireframeOnShadedFull;
}
else if (wireframeOnShadedActive == "reduced") {
fsWireframeOnShadedMode = kWireframeOnShadedReduced;
}
else if (wireframeOnShadedActive == "none") {
fsWireframeOnShadedMode = kWireframeOnShadedNone;
}
else {
assert(0);
}
}
}
DisplayPref::WireframeOnShadedMode DisplayPref::wireframeOnShadedMode()
{
return fsWireframeOnShadedMode;
}
void* ShapeUI::creator()
{
return new ShapeUI;
}
ShapeUI::ShapeUI()
{}
ShapeUI::~ShapeUI()
{}
void ShapeUI::getDrawRequests(
const MDrawInfo & info,
bool objectAndActiveOnly,
{
ShapeNode::init3dViewPostRenderCallbacks();
getDrawData( 0, data );
return;
}
switch ( appearance )
{
{
}break;
{
} break;
default:
{
ShapeNode* node = (ShapeNode*)surfaceShape();
if (!node) break;
const SubNode::Ptr geom = node->getCachedGeometry();
if (!geom) break;
const DrawToken shadedDrawToken = needWireframe ?
kDrawSmoothShadedDepthOffset : kDrawSmoothShaded;
}
}
}
else {
if (geom->transparentType() != SubNode::kTransparent) {
}
if (geom->transparentType() != SubNode::kOpaque) {
}
}
if (needWireframe &&
DisplayPref::wireframeOnShadedMode() != DisplayPref::kWireframeOnShadedNone)
{
wireRequest.
setToken( kDrawWireframeOnShaded );
queue.
add( wireRequest );
}
} break;
}
}
{
InitializeGLFT();
DrawToken token = DrawToken(request.
token());
switch( token )
{
case kBoundingBox :
drawBoundingBox( request, view );
break;
case kDrawWireframe :
case kDrawWireframeOnShaded :
drawWireframe( request, view );
break;
case kDrawSmoothShaded :
drawShaded( request, view, false );
break;
case kDrawSmoothShadedDepthOffset :
drawShaded( request, view, true );
break;
}
}
{
ShapeNode* node = (ShapeNode*)surfaceShape();
if (!node) return;
{
bool lightingWasOn = gGLFT->glIsEnabled( MGL_LIGHTING ) == MGL_TRUE;
if ( lightingWasOn ) {
gGLFT->glDisable( MGL_LIGHTING );
}
gGLFT->glEnable( MGL_LINE_STIPPLE );
gGLFT->glLineStipple(1, Config::kLineStippleShortDashed);
VBOProxy vboProxy;
vboProxy.drawBoundingBox(box);
if ( lightingWasOn ) {
gGLFT->glEnable( MGL_LIGHTING );
}
gGLFT->glDisable( MGL_LINE_STIPPLE );
}
}
{
ShapeNode* node = (ShapeNode*)surfaceShape();
if ( !node ) return;
const SubNode::Ptr rootNode = node->getCachedGeometry();
if (!rootNode) return;
MMatrix localToPort = modelViewMatrix * projMatrix;
{
bool lightingWasOn = gGLFT->glIsEnabled( MGL_LIGHTING ) == MGL_TRUE;
if ( lightingWasOn ) {
gGLFT->glDisable( MGL_LIGHTING );
}
gGLFT->glEnable( MGL_LINE_STIPPLE );
if (request.
token() == kDrawWireframeOnShaded) {
DisplayPref::WireframeOnShadedMode wireframeOnShadedMode =
DisplayPref::wireframeOnShadedMode();
if (wireframeOnShadedMode == DisplayPref::kWireframeOnShadedReduced) {
gGLFT->glLineStipple(1, Config::kLineStippleDotted);
}
else {
assert(wireframeOnShadedMode != DisplayPref::kWireframeOnShadedNone);
gGLFT->glLineStipple(1, Config::kLineStippleShortDashed);
}
}
else {
gGLFT->glLineStipple(1, Config::kLineStippleShortDashed);
}
{
Frustum frustum(localToPort.
inverse());
DrawWireframeState state(frustum, seconds);
DrawWireframeTraversal traveral(state, xform, false, Frustum::kUnknown);
rootNode->accept(traveral);
}
if ( lightingWasOn ) {
gGLFT->glEnable( MGL_LIGHTING );
}
gGLFT->glDisable( MGL_LINE_STIPPLE );
}
}
void ShapeUI::drawShaded(
{
ShapeNode* node = (ShapeNode*)surfaceShape();
if ( !node ) return;
const SubNode::Ptr rootNode = node->getCachedGeometry();
if (!rootNode) return;
MMatrix localToNDC = modelViewMatrix * projMatrix;
unsigned int lightCount;
const bool noLightSoDrawAsBlack =
&& lightCount == 0;
{
gGLFT->glPushAttrib(MGL_LIGHTING_BIT);
{
static const float sBlack[4] = {0.0f, 0.0f, 0.0f, 1.0f};
gGLFT->glMaterialfv(MGL_FRONT_AND_BACK, MGL_SPECULAR, sBlack);
gGLFT->glMaterialfv(MGL_FRONT_AND_BACK, MGL_EMISSION, sBlack);
}
DrawShadedState::TransparentPruneType transparentPrune =
DrawShadedState::kPruneTransparent;
if (isTransparent) {
gGLFT->glBlendFunc(MGL_ONE, MGL_ONE_MINUS_SRC_ALPHA);
transparentPrune = DrawShadedState::kPruneOpaque;
gGLFT->glDepthMask( false );
}
DrawShadedTypes::ColorType colorType = DrawShadedTypes::kSubNodeColor;
if (!noLightSoDrawAsBlack) {
}
defaultDiffuseColor[3] = 1.0f;
transparentPrune = DrawShadedState::kPruneNone;
colorType = DrawShadedTypes::kDefaultColor;
}
transparentPrune = DrawShadedState::kPruneNone;
if (noLightSoDrawAsBlack) {
defaultDiffuseColor =
MColor(0, 0, 0, 0.3f);
colorType = DrawShadedTypes::kDefaultColor;
}
else {
colorType = DrawShadedTypes::kXrayColor;
}
}
else if (noLightSoDrawAsBlack) {
colorType = DrawShadedTypes::kBlackColor;
}
if (noLightSoDrawAsBlack) {
gGLFT->glDisable(MGL_LIGHTING);
}
const bool depthOffsetWasEnabled = gGLFT->glIsEnabled(MGL_POLYGON_OFFSET_FILL);
if (depthOffset && !depthOffsetWasEnabled) {
gGLFT->glEnable(MGL_POLYGON_OFFSET_FILL);
}
gGLFT->glColorMaterial(MGL_FRONT_AND_BACK, MGL_AMBIENT_AND_DIFFUSE);
gGLFT->glEnable(MGL_COLOR_MATERIAL) ;
bool needEmulateTwoSidedLighting = false;
if (Config::emulateTwoSidedLighting()) {
bool cullFace = (gGLFT->glIsEnabled(MGL_CULL_FACE) == MGL_TRUE);
MGLint twoSidedLighting = MGL_FALSE;
gGLFT->glGetIntegerv(MGL_LIGHT_MODEL_TWO_SIDE, &twoSidedLighting);
needEmulateTwoSidedLighting = (!cullFace && twoSidedLighting);
}
{
Frustum frustum(localToNDC.
inverse());
if (needEmulateTwoSidedLighting) {
gGLFT->glEnable(MGL_CULL_FACE);
gGLFT->glLightModeli(MGL_LIGHT_MODEL_TWO_SIDE, 0);
{
gGLFT->glCullFace(MGL_FRONT);
DrawShadedState state(frustum,
seconds,
transparentPrune,
colorType,
defaultDiffuseColor,
DrawShadedState::kBackNormals);
DrawShadedTraversal traveral(
state, xform, xform.det3x3() < 0.0, Frustum::kUnknown);
rootNode->accept(traveral);
}
{
gGLFT->glCullFace(MGL_BACK);
DrawShadedState state(frustum,
seconds,
transparentPrune,
colorType,
defaultDiffuseColor,
DrawShadedState::kFrontNormals);
DrawShadedTraversal traveral(
state, xform, xform.det3x3() < 0.0, Frustum::kUnknown);
rootNode->accept(traveral);
}
gGLFT->glDisable(MGL_CULL_FACE);
gGLFT->glLightModeli(MGL_LIGHT_MODEL_TWO_SIDE, 1);
}
else {
DrawShadedState state(frustum,
seconds,
transparentPrune,
colorType,
defaultDiffuseColor,
DrawShadedState::kFrontNormals);
DrawShadedTraversal traveral(
state, xform, xform.det3x3() < 0.0, Frustum::kUnknown);
rootNode->accept(traveral);
}
}
if (isTransparent) {
gGLFT->glDepthMask( true );
gGLFT->glBlendFunc(MGL_SRC_ALPHA, MGL_ONE_MINUS_SRC_ALPHA);
}
if (depthOffset && !depthOffsetWasEnabled) {
gGLFT->glDisable(MGL_POLYGON_OFFSET_FILL);
}
gGLFT->glFrontFace(MGL_CCW);
gGLFT->glPopAttrib();
}
}
MPoint ShapeUI::getPointAtDepth(
double depth)
{
if (!camera.isOrtho())
{
double np = camera.nearClippingPlane();
double fp = camera.farClippingPlane();
depth *= np / (fp - depth * (fp - np));
}
short x,y;
res = neardb + depth*(fardb-neardb);
return res;
}
bool ShapeUI::select(
{
InitializeGLFT();
return false;
}
return false;
}
ShapeNode* node = (ShapeNode*)surfaceShape();
const SubNode::Ptr rootNode = node->getCachedGeometry();
if (!rootNode) { return false;}
const bool boundingboxSelection =
const bool wireframeSelection =
VBOProxy::VBOMode vboMode = VBOProxy::kUseVBOIfPossible;
if (Config::vp2OverrideAPI() != Config::kMPxDrawOverride) {
vboMode = (sModelEditorState == kViewport2Only) ?
VBOProxy::kDontUseVBO : VBOProxy::kUseVBOIfPossible;
}
GLfloat minZ;
{
Select* selector;
NbPrimitivesVisitor nbPrimitives(seconds);
rootNode->accept(nbPrimitives);
if (boundingboxSelection) {
selector = new GLPickingSelect(selectInfo);
selector->processBoundingBox(rootNode, seconds);
}
else if (wireframeSelection) {
if (nbPrimitives.numWires() < Config::openGLPickingWireframeThreshold())
selector = new GLPickingSelect(selectInfo);
else
selector = new RasterSelect(selectInfo);
selector->processEdges(rootNode, seconds, nbPrimitives.numWires(), vboMode);
}
else {
if (nbPrimitives.numTriangles() < Config::openGLPickingSurfaceThreshold())
selector = new GLPickingSelect(selectInfo);
else
selector = new RasterSelect(selectInfo);
selector->processTriangles(rootNode, seconds, nbPrimitives.numTriangles(), vboMode);
}
selector->end();
minZ = selector->minZ();
delete selector;
}
bool selected = (minZ <= 1.0f);
if ( selected ) {
{
{
{
break;
}
else
{
}
}
}
MPoint worldSpaceselectionPoint =
getPointAtDepth(selectInfo, minZ);
selectionItem,
worldSpaceselectionPoint,
selectionList, worldSpaceSelectPts,
mask, false );
}
return selected;
}
{
InitializeGLFT();
return false;
}
ShapeNode* node = (ShapeNode*)surfaceShape();
const SubNode::Ptr rootNode = node->getCachedGeometry();
if (!rootNode) return false;
unsigned int vpx, vpy, vpw, vph;
double w_over_two = vpw * 0.5;
double h_over_two = vph * 0.5;
double vpoff_x = w_over_two + vpx;
double vpoff_y = h_over_two + vpy;
ndcToPort(0,0) = w_over_two;
ndcToPort(1,1) = h_over_two;
ndcToPort(2,2) = 0.5;
ndcToPort(3,0) = vpoff_x;
ndcToPort(3,1) = vpoff_y;
ndcToPort(3,2) = 0.5;
const MMatrix localToNDC = modelViewMatrix * projMatrix;
const MMatrix localToPort = localToNDC * ndcToPort;
Frustum frustum(localToNDC.
inverse());
SnapTraversalState state(
frustum, seconds, localToPort, inclusiveMatrix, snapInfo);
rootNode->accept(visitor);
return state.selected();
}
{
addExternalContentForFileAttr(table, aCacheFileName);
}
{
setExternalContentForFileAttr(aCacheFileName, table);
}
}