[Closed] [SDK] IntersectRay troubles
Hi there,
I recently became a dev for my employer’s 3D design department and you people have already been a huge help in my endeavors to rewrite an old, old MaxScript into a plugin (for performance reasons) but I’ve kinda hit a snag with the IntersectRay function that I can’t really find a solution for.
I’ve already seen that IntersectRay isn’t the best way, but it really only gets called for maybe 20 specific objects, so it shouldn’t be an issue.
Okay, so here’s the code from my test plugin:
int RefTest::PewPew(MSTR nodeName, MSTR targetname)
{
// Create Interface and Node Pointers
Interface* ip = GetCOREInterface();
if (!ip) return 1;
INode* inCaster = ip->GetINodeByName(nodeName);
if (!inCaster) return 1;
INode* inTarget = ip->GetINodeByName(targetname);
if (!inTarget) return 1;
Point3 rayCasterPosition(0, 0, 0);
Point3 surfaceNormal(0, 0, 0);
float intersectPosition = 0.0f;
ip->GetINodeByName(nodeName)->GetTMController()->GetPositionController()->GetValue(0, &rayCasterPosition, FOREVER, CTRL_ABSOLUTE);
Ray positionRay(rayCasterPosition, Point3(0, 0, 1));
if (inTarget->GetObjectRef()->IntersectRay(0, positionRay, intersectPosition, surfaceNormal))
{
MSTR s(_T("HIT!"));
RefTest::GetInstance()->SetText(s);
}
else
{
MSTR s(_T("MISS!"));
RefTest::GetInstance()->SetText(s);
}
return 0;
}
nodeName being the node whose position should be used for the ray’s origin and targetName obviously for the target object.
For testing purposes, I simply created two boxes and passed the names to the function.
Now the issue is that I don’t actually get a hit when I place the raycaster underneath the target box.
I DO however get hits when I place it below 0,0,0, no matter where the target box is.
Going by the value I get in intersectionPosition, that seems to be what I’m receiving hits for.
The other weird thing is that the surfaceNormal values always end up being 0, 0, -1
What am I doing wrong here?
Thanks a lot!
you need to working in object space to call intersectRay, so the ray needs to xformed into object space from it’s world space coords you are using to work properly… here’s how the mxs function does it…
Value*
IntersectRayEx_cf(Value** arg_list, int count)
{
float at;
Point3 pt, normal, bary;
Ray ray, os_ray;
GeomObject* obj;
DWORD fi;
check_arg_count(intersectRayEx, 2, count);
INode* node = get_valid_node(arg_list[0], intersectRayEx);
// Get the object from the node
ObjectState os = node->EvalWorldState(MAXScript_time());
if (os.obj->SuperClassID()==GEOMOBJECT_CLASS_ID) {
obj = (GeomObject*)os.obj;
if (obj->ClassID() != GetEditTriObjDesc()->ClassID() &&
obj->ClassID() != Class_ID(TRIOBJ_CLASS_ID, 0))
return &undefined;
}
else
return &undefined;
// Back transform the ray into object space.
Matrix3 obtm = node->GetObjectTM(MAXScript_time());
Matrix3 iobtm = Inverse(obtm);
ray = arg_list[1]->to_ray();
os_ray.p = iobtm * ray.p;
os_ray.dir = VectorTransform(iobtm, ray.dir);
// See if we hit the object
if (((TriObject*)obj)->GetMesh().IntersectRay(os_ray, at, normal, fi, bary))
{
// Calculate the hit point
pt = os_ray.p + os_ray.dir * at;
// transform back into world space & build result ray
pt = pt * obtm;
normal = Normalize(VectorTransform(obtm, normal));
// Return the array containing the intersection details
one_typed_value_local(Array* result);
vl.result = new Array(3);
vl.result->append(new RayValue (pt, normal));
vl.result->append(Integer::intern (fi+1));
vl.result->append(new Point3Value (bary));
return_value (vl.result); // LAM - 5/18/01 - was return vl.result
}
else
return &undefined;
}
The ray intersection methods were broken after Max 2016 and haven’t been fixed yet. Someone from Autodesk recently said it’s been fixed and tested internally, though they didn’t mention when it would be released to the public.
Here is a link to that post, which also links to my post which has a test case that illustrates the issue with intersectray:
What I found is that it was broken with edit poly objects, but worked fine with edit mesh or primitives. Until they release a fix, you could convert edit poly objects to edit mesh.
don’t think it’s ever worked with editable poly as you can see from the above code if it’s not trimesh then it returns undefined.
Blockquote
I misspoke about edit poly objects not working, that was for IntersectRayScene.
I use edit poly objects with no issue calling intersectRay in conjunction with RayMeshGridIntersect() and addnode.
Woo! Thanks a lot!
That’s exactly what I needed!
I just added
Matrix3 obtm = inTarget->GetObjectTM(0);
Matrix3 iobtm = Inverse(obtm);
Ray os_positionRay((iobtm * positionRay.p), VectorTransform(iobtm, positionRay.dir));
and
hitPoint = os_positionRay.p + os_positionRay.dir * intersectPosition;
hitPoint = hitPoint * obtm;
on a hit and I got the data I needed.
Say… can I actually find all the MXS function implementations in maxsdk\samples\maxscript?
Because hoo boy do I feel stupid for not checking there before.
yes (well not all but a lot of them) it’s in the mxsagni project in the samples