📄 cvbound.cpp
字号:
// Instance Bounds computers - the wave of the future
// First the helpers - these are pretty local
bool GetBoundingCube(QvMFLong *pCoordIndex, QvCoordinate3 *pC3, GxVec3f &lower, GxVec3f &upper, GxVec3f ¢er )
{
lower.set(BIGGIE, BIGGIE, BIGGIE);
upper.set(-BIGGIE, -BIGGIE, -BIGGIE);
center.set(0., 0., 0.);
int count = 0;
for( int j = 0; j< pCoordIndex->num; j++)
{
if (pCoordIndex->values[j] != QV_END_FACE_INDEX)
{
int index = pCoordIndex->values[j] * 3;
#if 1
// Should be faster this way!
GxVec3f *p = (GxVec3f*)(pC3->point.values+index); // ASSUMES ALIGNMENT!!
lower.minimum(*p);
upper.maximum(*p);
center += *p;
#else
lower.x() = min(lower.x(), pC3->point.values[index]);
lower.y() = min(lower.y(), pC3->point.values[index+1]);
lower.z() = min(lower.z(), pC3->point.values[index+2]);
upper.x() = max(upper.x(), pC3->point.values[index]);
upper.y() = max(upper.y(), pC3->point.values[index+1]);
upper.z() = max(upper.z(), pC3->point.values[index+2]);
center.x() += pC3->point.values[index];
center.y() += pC3->point.values[index+1];
center.z() += pC3->point.values[index+2];
#endif
count++;
}
}
if(count>0)
{
center.x() /= count;
center.y() /= count;
center.z() /= count;
}
return true;
}
// Then the Node Instances
bool ChQvIFSInstance::ComputeBounds()
{
if(!m_pBounds) m_pBounds = new ChQvBounds;
GxVec3f upper, lower, center;
QvCoordinate3 *pC3 = GetCoordinate3();
GetBoundingCube( &(((QvIndexedFaceSet*)GetNode())->coordIndex), pC3, lower, upper, center);
m_pBounds->SetBounds(lower, upper);
m_pBounds->SetCenter(center);
m_pBounds->SetTransform(GetTransform());
m_boolBoundsDirty = false;
return true;
};
bool ChQvILSInstance::ComputeBounds()
{
if(!m_pBounds) m_pBounds = new ChQvBounds;
GxVec3f upper, lower, center;
QvCoordinate3 *pC3 = GetCoordinate3();
GetBoundingCube( &(((QvIndexedLineSet*)GetNode())->coordIndex), pC3, lower, upper, center);
m_pBounds->SetBounds(lower, upper);
m_pBounds->SetCenter(center);
m_pBounds->SetTransform(GetTransform());
m_boolBoundsDirty = false;
return true;
};
bool ChQvCubeInstance::ComputeBounds()
{
if(!m_pBounds) m_pBounds = new ChQvBounds;
GxVec3f lower, upper, center(0.,0.,0);
QvCube * pCube = (QvCube *)GetNode();
lower.x() = -pCube->width.value / 2.;
lower.y() = -pCube->height.value / 2.;
lower.z() = -pCube->depth.value / 2.;
upper.x() = pCube->width.value / 2.;
upper.y() = pCube->height.value / 2.;
upper.z() = pCube->depth.value / 2.;
m_pBounds->SetBounds(lower, upper);
m_pBounds->SetCenter(center);
m_pBounds->SetTransform(GetTransform());
m_boolBoundsDirty = false;
return 1;
};
int ChQvConeInstance::ComputeBounds()
{
if(!m_pBounds) m_pBounds = new ChQvBounds;
GxVec3f lower, upper, center(0.,0.,0);
QvCone * pCone = (QvCone *)GetNode();
lower.x() = -pCone->bottomRadius.value;
lower.y() = -pCone->height.value / 2.;
lower.z() = -pCone->bottomRadius.value;
upper.x() = pCone->bottomRadius.value;
upper.y() = pCone->height.value / 2.;
upper.z() = pCone->bottomRadius.value;
m_pBounds->SetBounds(lower, upper);
m_pBounds->SetCenter(center);
m_pBounds->SetTransform(GetTransform());
m_boolBoundsDirty = false;
return 1;
};
int ChQvSphereInstance::ComputeBounds()
{
if(m_boolBoundsDirty)
{
if(!m_pBounds) m_pBounds = new ChQvBounds;
GxVec3f lower, upper, center(0.,0.,0);
QvSphere * pSphere = (QvSphere *)GetNode();
lower.x() = -pSphere->radius.value;
lower.y() = -pSphere->radius.value;
lower.z() = -pSphere->radius.value;
upper.x() = pSphere->radius.value;
upper.y() = pSphere->radius.value;
upper.z() = pSphere->radius.value;
m_pBounds->SetBounds(lower, upper);
m_pBounds->SetCenter(center);
m_pBounds->SetTransform(GetTransform());
m_boolBoundsDirty = false;
m_boolBoundsDirty = false;
}
return 1;
};
const float fMinInlineBox = 1.0e-6;
int ChQvWWWInlineInstance::ComputeBounds()
{
if(!m_pBounds) m_pBounds = new ChQvBounds;
QvWWWInline * pWWWInline = (QvWWWInline *)GetNode();
GxVec3f lower, upper, center;
float fHalfWidth = pWWWInline->bboxSize.value[0] / 2.0;
float fHalfHeight = pWWWInline->bboxSize.value[1] / 2.0;
float fHalfDepth = pWWWInline->bboxSize.value[2] / 2.0;
if(fHalfWidth <= 0.0) fHalfWidth = fMinInlineBox;
if(fHalfHeight <= 0.0) fHalfHeight = fMinInlineBox;
if(fHalfDepth <= 0.0) fHalfDepth = fMinInlineBox;
upper.x() = fHalfWidth;
upper.y() = fHalfHeight;
upper.z() = fHalfDepth;
lower.x() = -fHalfWidth;
lower.y() = -fHalfHeight;
lower.z() = -fHalfDepth;
center.x() = pWWWInline->bboxCenter.value[0];
center.y() = pWWWInline->bboxCenter.value[1];
center.z() = pWWWInline->bboxCenter.value[2];
m_pBounds->SetBounds(lower, upper);
m_pBounds->SetCenter(center);
m_pBounds->SetTransform(GetTransform());
m_boolBoundsDirty = false;
return 1;
};
int ChQvCylinderInstance::ComputeBounds()
{
if(!m_pBounds) m_pBounds = new ChQvBounds;
GxVec3f lower, upper, center(0.,0.,0);
QvCylinder * pCylinder = (QvCylinder *)GetNode();
lower.x() = -pCylinder->radius.value;
lower.y() = -pCylinder->height.value / 2.;
lower.z() = -pCylinder->radius.value;
upper.x() = pCylinder->radius.value;
upper.y() = pCylinder->height.value / 2.;
upper.z() = pCylinder->radius.value;
m_pBounds->SetBounds(lower, upper);
m_pBounds->SetCenter(center);
m_pBounds->SetTransform(GetTransform());
m_boolBoundsDirty = false;
return 1;
};
int ChQvAsciiTextInstance::ComputeBounds()
{
if(!m_pBounds) m_pBounds = new ChQvBounds;
QvAsciiText *pNode = (QvAsciiText *)m_pNode;
if(!m_pBounds) m_pBounds = new ChQvBounds;
GxVec3f lower, upper, center(0.,0.,0);
HFONT hFont = CreateFont(100);
float maxWidth = 0.0;
for(int line = 0; line < pNode->string.num; line++)
{
float width = GetTextWidth(hFont, line);
maxWidth = max(width, maxWidth);
}
switch(pNode->justification.value)
{
case QvAsciiText::LEFT:
lower.x() = 0.;
break;
case QvAsciiText::RIGHT:
lower.x() = -maxWidth;
break;
case QvAsciiText::CENTER:
lower.x() = -maxWidth / 2;
break;
}
upper.x() = lower.x() + maxWidth;
upper.y() = -GetBaselineOffset() - line * pNode->spacing.value * GetFontStyle()->size.value;
lower.y() = upper.y() - GetTextHeight();
upper.z() = 0.0;
lower.z() = -.01; // give it a bit of depth, for safety
center = lower;
center += upper;
center *= .5;
DeleteObject(hFont);
m_pBounds->SetBounds(lower, upper);
m_pBounds->SetCenter(center);
m_pBounds->SetTransform(GetTransform());
m_boolBoundsDirty = false;
return 1;
};
int ChQvPointSetInstance::ComputeBounds()
{
if(!m_pBounds) m_pBounds = new ChQvBounds;
QvPointSet *pNode = (QvPointSet *)GetNode();
QvCoordinate3 *pC3 = GetCoordinate3();
GxVec3f lower, upper, center(0.,0.,0);
lower.set(BIGGIE, BIGGIE, BIGGIE);
upper.set(-BIGGIE, -BIGGIE, -BIGGIE);
center.set(0., 0., 0.);
int count = 0;
int numPoints = pNode->numPoints.value;
if(numPoints < 0)
{
numPoints = pC3->point.num - pNode->startIndex.value;
}
for(int j = pNode->startIndex.value; j < numPoints + pNode->startIndex.value; j++)
{
int index = j * 3;
lower.x() = min(lower.x(), pC3->point.values[index]);
lower.y() = min(lower.y(), pC3->point.values[index+1]);
lower.z() = min(lower.z(), pC3->point.values[index+2]);
upper.x() = max(upper.x(), pC3->point.values[index]);
upper.y() = max(upper.y(), pC3->point.values[index+1]);
upper.z() = max(upper.z(), pC3->point.values[index+2]);
center.x() += pC3->point.values[index];
center.y() += pC3->point.values[index+1];
center.z() += pC3->point.values[index+2];
count++;
}
if(count>0)
{
center.x() /= count;
center.y() /= count;
center.z() /= count;
}
m_pBounds->SetBounds(lower, upper);
m_pBounds->SetCenter(center);
m_pBounds->SetTransform(GetTransform());
m_boolBoundsDirty = false;
return 1;
};
void ChBoundsIterator::Push()
{
ChBoundsStack *pStack = new ChBoundsStack(m_upper, m_lower, m_center, m_childBoundsCount, m_inverseTransform);
m_stack.AddHead(pStack);
}
bool ChBoundsIterator::Pop()
{
if(m_stack.IsEmpty()) return false;
ChBoundsStack *pStack = m_stack.RemoveHead();
m_upper = pStack->m_upper;
m_lower = pStack->m_lower;
m_center = pStack->m_center;
m_inverseTransform = pStack->m_inverseTransform;
m_childBoundsCount = pStack->m_childBoundsCount;
delete pStack;
return true;
}
ChBoundsIterator* ChBoundsIterator::LocalReset()
{
m_upper.set(0.,0.,0.);
m_lower.set(0.,0.,0.);
m_center.set(0.,0.,0.);
m_childBoundsCount = 0;
m_inverseTransform.Identity();
return this;
}
bool ChBoundsIterator::DoNode(ChQvInstance& inst)
{
switch(GetVisitType())
{
case beforeChildren:
{
Push();
LocalReset();
// set the inverse transform
m_inverseTransform = inst.GetTransform().Inverse();
#if 0
if(!inst.IsBoundsDirty()) SetDoKids(false);
#endif
break;
}
case afterChildren:
{
if(m_childBoundsCount)
{
m_center.x() /= m_childBoundsCount;
m_center.y() /= m_childBoundsCount;
m_center.z() /= m_childBoundsCount;
}
m_pBounds->SetBounds(m_lower, m_upper);
m_pBounds->SetCenter(m_center);
m_pBounds->SetTransform(inst.GetTransform());
Pop();
Accumulate();
// Get the bounds of group nodes, which are never
// called with VisitType "isLeaf".
if(inst.GetBounds(*GetBounds()))
{
Accumulate();
}
break;
}
case isLeaf:
{
if(inst.GetBounds(*GetBounds()))
{
Accumulate();
}
break;
}
}
return true;
}
void ChBoundsIterator::Accumulate()
{
if(!m_pBounds->IsEmpty())
{
m_childBoundsCount++;
GxTransform3Wf childMat;
GxVec3f childLower, childUpper;
m_pBounds->GetBounds(childLower, childUpper, childMat);
#if defined(CH_USE_3DR)
childMat = m_inverseTransform * childMat; // Get the child into the current object coord system
#else
childMat = childMat * m_inverseTransform; // Get the child into the current object coord system
#endif
//childMat = childMat.Compose(m_inverseTransform); // Get the child into the current object coord system
m_pBounds->GetTransformedBounds(childLower, childUpper, childMat);
if(m_childBoundsCount > 1)
{
m_lower.x() = min(m_lower.x(), childLower.x());
m_lower.y() = min(m_lower.y(), childLower.y());
m_lower.z() = min(m_lower.z(), childLower.z());
m_upper.x() = max(m_upper.x(), childUpper.x());
m_upper.y() = max(m_upper.y(), childUpper.y());
m_upper.z() = max(m_upper.z(), childUpper.z());
}
else
{
m_lower = childLower;
m_upper = childUpper;
}
GxVec3f childCenter;
m_pBounds->GetCenter(childCenter);
childCenter = childMat * childCenter;
m_center += childCenter;
}
}
// end of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -