📄 cvhittst.cpp
字号:
name.MakeLower();
if(!boolFound && name == "xch_hint")
{
hint = pChild->string.value.getString();
boolFound = true;
}
if(name == "xch_cmd")
{
cmd = pChild->string.value.getString();
}
}
}
}
if(!boolFound) // use the href as the hint
{
name = GetAnchorNode()->name.value.getString();
if(!name.IsEmpty() && name != "<Undefined info>")
{
hint = name;
boolFound = true;
}
}
if(!cmd.IsEmpty())
{
string tmp = hint;
hint = cmd;
if(boolFound)
{
hint += " (" + tmp + ")";
}
boolFound = true;
}
return boolFound;
}
#if defined(CH_USE_3DR)
#endif // CH_USE_3DR
bool ChHittestIterator::DoNode(ChQvInstance& inst)
{
bool boolKeepGoing = true;
switch(GetVisitType())
{
case beforeChildren:
{
bool ImHit = false;
// GetBounds && check em
ChQvBounds bounds;
inst.GetBounds(bounds);
//check instance's bounds
GxVec3f hPt;
ImHit = bounds.HitTest(GetRenderContext(), m_iX, m_iY, hPt); // hit me
SetDoKids(ImHit);
break;
}
case afterChildren:
{
break;
}
case isLeaf:
{
boolKeepGoing = true; // need logic for first find, etc here
inst.Hittest(GetRenderContext(), this);
break;
}
}
return boolKeepGoing;
};
void ChHittestIterator::Add(ChQvInstance *pInstance, const GxVec3f &pt)
{
m_instances.AddTail(ChInstanceHit(pInstance, pt));
};
bool ChHittestIterator::GetHit( ChQvInstance *& closest, GxVec3f &pt)
{
if(m_instances.IsEmpty()) return false;
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
float distance = 1e17; // way far away
ChPosition pos = m_instances.GetHeadPosition();
while (pos)
{
ChInstanceHit &bucket = m_instances.GetNext(pos);
// Transform to screen space
#if (defined(CH_USE_RLAB))
RLIMViewVertex ptInScreen;
RLIMTransformVertices
( GetRenderContext()->GetViewport(),
bucket.m_pInstance->GetFrame(),
(RLIMPositionVector*)&(bucket.m_pt),
&ptInScreen,
sizeof(RLIMPositionVector),
sizeof(RLIMViewVertex),
1,
1
);
bool boolUseIt = ptInScreen.sz >= 0 && ptInScreen.sz < distance;
if(boolUseIt)
{
distance = ptInScreen.sz;
closest = bucket.m_pInstance;
pt = bucket.m_pt;
}
#elif (defined(CH_USE_D3D) && defined(CH_IMMED_MODE))
#pragma message("D3D Immediate mode hittesting not done")
bool boolUseIt = false;
#endif
}
#endif
return true;
};
bool ChCollisionIterator::DoNode(ChQvInstance& inst)
{
bool boolKeepGoing = true;
switch(GetVisitType())
{
case beforeChildren:
{
bool ImHit = true;
// GetBounds && check em
ChQvBounds bounds;
inst.GetBounds(bounds);
//check group instance's bounds
GxVec3f hPt;
//ImHit = bounds.Test(GetRenderContext(), m_iX, m_iY, hPt); // hit me TODO ???????!!!!!!!!!!!!!!!
SetDoKids(ImHit);
break;
}
case afterChildren:
{
break;
}
case isLeaf:
{
boolKeepGoing = true; // need logic for first find, etc here
inst.CollisionTest(GetRenderContext(), this);
break;
}
}
return boolKeepGoing;
};
void ChCollisionIterator::Add(ChQvInstance *pInstance, float t)
{
m_instances.AddTail(ChInstanceHit(pInstance, t));
};
bool ChCollisionIterator::GetHit( ChQvInstance *& closest,float &t)
{
if(m_instances.IsEmpty()) return false;
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
ChPosition pos = m_instances.GetHeadPosition();
bool boolHit = false;
while (pos)
{
ChInstanceHit &bucket = m_instances.GetNext(pos);
if(!boolHit || (bucket.m_t < t && bucket.m_t >= 0))
{
boolHit = true;
closest = bucket.m_pInstance;
t = bucket.m_t;
}
}
return boolHit;
#endif
};
/* derived from Graphics Gems II intsph.c
/* ---- intsph - Intersect a ray with a sphere. ----------------------- */
/* */
/* */
/* Description: */
/* Intsph determines the intersection of a ray with a sphere. */
/* */
/* On entry: */
/* raybase = The coordinate defining the base of the */
/* intersecting ray. */
/* raycos = The direction cosines of the above ray. */
/* center = The center location of the sphere. */
/* radius = The radius of the sphere. */
/* */
/* On return: */
/* rin = The entering distance of the intersection. */
/* rout = The leaving distance of the intersection. */
/* */
/* Returns: True if the ray intersects the sphere. */
/* */
/* -------------------------------------------------------------------- */
int intsph(const GxVec3f &raybase, const GxVec3f &raycos, const GxVec3f ¢er, float radius, float &rin, float &rout)
{
int hit; /* True if ray intersects sphere*/
double dx, dy, dz; /* Ray base to sphere center */
double bsq, u, disc;
double root;
dx = raybase.x() - center.x();
dy = raybase.y() - center.y();
dz = raybase.z() - center.z();
bsq = dx*raycos.x() + dy*raycos.y() + dz*raycos.z();
u = dx*dx + dy*dy + dz*dz - radius*radius;
disc = bsq*bsq - u;
hit = (disc >= 0.0);
if (hit) { /* If ray hits sphere */
root = sqrt(disc);
rin = -bsq - root; /* entering distance */
rout = -bsq + root; /* leaving distance */
}
return (hit);
}
bool ChQvSphereInstance::Hittest(ChRenderContext *pRC, ChHittestIterator *pIterator)
{
GxVec3f p, vec; // the line
int iX, iY;
pIterator->GetScreenPoint(iX, iY);
m_pBounds->SetTransform(GetTransform());; // refresh bounds
m_pBounds->PointWindowToObject(pRC, iX, iY, p, vec);
vec.normalize();
GxVec3f center(0, 0, 0); // always centered at 0 in object space
float rin, rout;
int hit = intsph(p, vec, center, ((QvSphere*)GetNode())->radius.value, rin, rout);
if(hit && (rin >= 0 || rout >= 0))
{
float t = (rin >= 0) ? rin : rout;
vec *= t;
vec += p;
pIterator->Add(this, vec);
}
return true;
}
bool ChQvSphereInstance::CollisionTest(ChRenderContext *pRC, ChCollisionIterator *pIterator)
{
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
// using rlab transforms here - otherwise portable
GxVec3f p0(pIterator->GetLoc()), vec(pIterator->GetDir()); // the line
float radius = pIterator->GetRadius();
GxVec3f center(0, 0, 0); // always centered at 0 in object space
float r = ((QvSphere*)GetNode())->radius.value;
// now transform camera loc and dir to object - they are in world now
GxVec3f vecObj, p0Obj;
vec += p0;
vec.z() = -vec.z();
p0.z() = -p0.z();
ChNrFrameInverseTransform(m_frame, (ChNrVector*)&vecObj, (ChNrVector*)&vec);
ChNrFrameInverseTransform(m_frame, (ChNrVector*)&p0Obj, (ChNrVector*)&p0);
vecObj -= p0Obj;
// R is a problem TODO !!!!!!!!!!!!
float t;
int hit = MovingSphereToSphere(p0Obj, vecObj, radius, center, r, t);
if(hit && (t >= 0.0))
{
pIterator->Add(this, t);
}
#endif
return true;
}
#if (defined(CH_USE_RLAB))
bool ChRenderContext::GetHitPoint(int iX, int iY, GxVec3f &pt)
{
// ix and iY are in screen coords; pt is in -world- coords
bool boolHit = false;
if(m_viewport)
{
ChNrFrame frame;
// Lock the scene and don't be nice
LockScene();
RLVisual visual;
const float aTinyBit = 1e-6;
if(ChNrViewportFindVisual( m_viewport, &visual, &frame, iX, iY) != RLNotFound)
{
// Hit -something-. How far away is it?
GxVec3f clickPoint, framePoint;
ChNrFaceInfo faceInfo;
ChNrVector4d screenCoord, frameScreenCoord;
ChNrFrameGetPosition(frame, m_sceneFrame, (ChNrVector*)&framePoint);
ChNrViewportTransform(m_viewport, &frameScreenCoord, (ChNrVector*)&framePoint);
float fVisualFrameZ = ((frameScreenCoord.w != 0.0) ? (frameScreenCoord.z / frameScreenCoord.w) : 0.0);
RLError foundIt = ChNrViewportFindFace( m_viewport, &faceInfo, iX, iY);
if( foundIt != RLNotFound )
{
ChNrFrameGetPosition(faceInfo.frame, m_sceneFrame, (ChNrVector*)&clickPoint);
ChNrViewportTransform(m_viewport, &frameScreenCoord, (ChNrVector*)&clickPoint);
float fFaceFrameZ = ((frameScreenCoord.w != 0.0) ? (frameScreenCoord.z / frameScreenCoord.w) : 0.0);
if(faceInfo.frame == frame || fFaceFrameZ <= fVisualFrameZ + aTinyBit )
{
clickPoint = *(GxVec3f*)&faceInfo.position;
screenCoord.x = clickPoint.x();
screenCoord.y = clickPoint.y();
screenCoord.z = clickPoint.z();
screenCoord.w = 1;
ChNrViewportInverseTransform(m_viewport, (ChNrVector*)&clickPoint, &screenCoord);
}
else
{
// It's not a face visual, must be a decal
clickPoint = framePoint;
}
}
else
{
// It's not a face visual, must be a decal
clickPoint = framePoint;
}
// Convert to world coords
ChNrFrameInverseTransform(m_sceneFrame, (ChNrVector*)&pt, (ChNrVector*)&clickPoint);
boolHit = true;
}
// Now see if it's in the immediate render world
#if defined(CH_IMMED_MODE)
{
ChHittestIterator iterator(this, iX, iY);
iterator.Attach(GetRoot());
iterator.Iterate();
ChQvInstance *pInst;
GxVec3f immpt;
if(iterator.GetHit(pInst, immpt))
{
ChNrFrame hitFrame = pInst->GetFrame();
bool boolIsClosest = true;
if(boolHit)
{
RLIMViewVertex ptInScreen;
#if 1
RLIMTransformVertices
( GetViewport(),
m_sceneFrame,
(RLIMPositionVector*)&(pt),
&ptInScreen,
sizeof(RLIMPositionVector),
sizeof(RLIMViewVertex),
1,
1
);
#endif
float retainedZ = ptInScreen.sz;
RLIMTransformVertices
( GetViewport(),
hitFrame,
(RLIMPositionVector*)&(immpt),
&ptInScreen,
sizeof(RLIMPositionVector),
sizeof(RLIMViewVertex),
1,
1
);
float immedZ = ptInScreen.sz;
boolIsClosest = immedZ < retainedZ;
}
if(boolIsClosest)
{
GxVec3f tmp;
ChNrFrameTransform(hitFrame, (ChNrVector*)&tmp, (ChNrVector*)&immpt);
ChNrFrameInverseTransform(m_sceneFrame, (ChNrVector*)&pt, (ChNrVector*)&tmp);
boolHit = true;
}
}
}
#endif
UnlockScene();
}
return boolHit;
}
//#if 0
#elif (defined(CH_USE_D3D))
bool ChRenderContext::GetHitPoint(int iX, int iY, GxVec3f &pt)
{
// ix and iY are in screen coords; pt is in -world- coords
bool boolHit = false;
if(m_viewport)
{
// Lock the scene and don't be nice
LockScene();
GxVec3f retainedPoint;
LPDIRECT3DRMVISUAL visual;
LPDIRECT3DRMFRAME pickFrame;
LPDIRECT3DRMPICKEDARRAY picked = 0;
LPDIRECT3DRMFRAMEARRAY frames;
LPDIRECT3DRMMESHBUILDER mesh;
LPDIRECT3DRMTEXTURE decal;
D3DRMPICKDESC pickInfo;
HRESULT rval = m_viewport->Pick(iX, iY, &picked);
int count = picked ? picked->GetSize() : 0;
float z = 0;
if(count > 0)
{
picked->GetPick(0, &visual, &frames, &pickInfo);
frames->GetElement(frames->GetSize() - 1, &pickFrame);
if (SUCCEEDED(visual->QueryInterface(IID_IDirect3DRMMeshBuilder, (void **) &mesh)))
{
mesh->Release();
boolHit = true;
}
else if (SUCCEEDED(visual->QueryInterface(IID_IDirect3DRMTexture, (void **) &decal)))
{
decal->Release();
boolHit = true;
}
pickFrame->Release();
frames->Release();
visual->Release();
GxVec3f clickPoint;
ChNrVector4d screenCoord;
screenCoord.x = pickInfo.vPosition.x;
screenCoord.y = pickInfo.vPosition.y;
screenCoord.z = pickInfo.vPosition.z;
screenCoord.w = 1;
ChNrViewportInverseTransform(m_viewport, (ChNrVector*)&clickPoint, &screenCoord);
ChNrFrameInverseTransform(m_sceneFrame, (ChNrVector*)&pt, (ChNrVector*)&clickPoint);
}
UnlockScene();
}
return boolHit;
};
#endif
//#endif
// end of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -