void ProtHelpObject::GetMat(TimeValue t, INode* inode, ViewExp& vpt, Matrix3& tm) { if ( ! vpt.IsAlive() ) { tm.Zero(); return; } tm = inode->GetObjectTM(t); tm.NoScale(); float scaleFactor = vpt.NonScalingObjectSize() * vpt.GetVPWorldWidth(tm.GetTrans()) / 360.0f; tm.Scale(Point3(scaleFactor,scaleFactor,scaleFactor)); }
static BOOL clipgrid(Point3 wp, ViewExp& vpt) { if ( ! vpt.IsAlive() ) { // why are we here DbgAssert(!_T("Invalid viewport!")); return FALSE; } if(!vpt.IsPerspView()) return TRUE; float minx, miny, maxx, maxy; vpt.GetGridDims(&minx, &maxx, &miny, &maxy); if(wp.x > minx && wp.x < maxx && wp.y > miny && wp.y < maxy) return TRUE; return FALSE; }
void TweakMouseProc::ComputeNewUVW(ViewExp& vpt, IPoint2 m) { if ( ! vpt.IsAlive() ) { // why are we here DbgAssert(!_T("Invalid viewport!")); return; } Ray r; vpt.MapScreenToWorldRay ((float) m.x, (float) m.y, r); TimeValue t = GetCOREInterface()->GetTime(); Matrix3 tm = mod->GetMeshTopoDataNode(mHitLDIndex)->GetObjectTM(t); Matrix3 itm = Inverse(tm); r.p = r.p * itm; r.dir = VectorTransform(r.dir,itm); //intersect our ray with that face and get our new bary coords Point3 n = mHitLD->GetGeomFaceNormal(mHitFace); Point3 p1, p2, p3; p1 = mHitP[0]; p2 = mHitP[1]; p3 = mHitP[2]; Point3 p, bry; float d, rn, a; // See if the ray intersects the plane (backfaced) rn = DotProd(r.dir,n); if (rn > -0.0001) return; // Use a point on the plane to find d Point3 v1 = p1; d = DotProd(v1,n); // Find the point on the ray that intersects the plane a = (d - DotProd(r.p,n)) / rn; // Must be positive... if (a < 0.0f) return ; // The point on the ray and in the plane. p = r.p + a*r.dir; // Compute barycentric coords. bry = BaryCoords(p1,p2,p3,p); // DbgAssert(bry.x + bry.y+ bry.z = 1.0) Point3 uvw = mHitUVW[0] * bry.x + mHitUVW[1] * bry.y + mHitUVW[2] * bry.z; Point3 v = uvw - mSourceUVW; v *= -1.0f; mFinalUVW = mSourceUVW + v; mHitLD->SetTVVert(GetCOREInterface()->GetTime(),mHitTVVert,mFinalUVW,mod); mod->NotifyDependents(FOREVER, PART_TEXMAP, REFMSG_CHANGE); mod->InvalidateView(); if (mod->ip) mod->ip->RedrawViews(mod->ip->GetTime()); }
void gridSnap::Snap(Object* pobj, IPoint2 *p, TimeValue t) { ViewExp *vpt = theman->GetVpt(); if ( ! vpt || ! vpt->IsAlive() ) { // why are we here DbgAssert(!_T("Invalid viewport!")); return; } DbgAssert(vpt != NULL); //local copy of the cursor position Point2 fp = Point2((float)p->x, (float)p->y); BOOL got_one= FALSE; //Get point on the consttruction plane Point3 local_cp = vpt->GetPointOnCP(*p); Point3 world_snapped; Matrix3 tmconst; vpt->GetConstructionTM( tmconst ); // aszabo|nov.01.05|#596889, #613720, #703875 // In order to allow snapping to the grid sub-divisions computed based on viewport // the zoom facto, the grid spacing is taken from the viewport. // When the grid is invisible and the zoom factor changes, the viewport returns // the grid spacing computed last time the grid was displayed. // When max starts up with hidden grids (via maxstart.max), the viewport's grid // spacing will be zero and in that case we take the grid spacing value specified // in the Grid setting UI. float gridSpacing = vpt->GetGridSize(); if (!(gridSpacing > 0.0f || gridSpacing < 0.0f)) { gridSpacing = GetCOREInterface()->GetGridSpacing(); } //Compute all the hit point candidates if( GetActive(INT_SUB)) { float gridZ = 0.f; #ifdef GAME_VER float gridSpacing = GetCOREInterface()->GetGridSpacing(); SnapInfo si; GetCOREInterface()->InitSnapInfo(&si); if(si.snapType == SNAP_25D) gridZ = GridCoord(local_cp.z,gridSpacing); Point3 intsnapped = Point3(GridCoord(local_cp.x,gridSpacing),GridCoord(local_cp.y,gridSpacing),gridZ); world_snapped = tmconst * intsnapped;//now in world space got_one = TRUE; hitmesh = new HitMesh(5); hitmesh->setVert(0,tmconst * Point3(intsnapped.x,intsnapped.y - gridSpacing,gridZ)); hitmesh->setVert(1,tmconst * Point3(intsnapped.x,intsnapped.y + gridSpacing,gridZ)); hitmesh->setVert(2,tmconst * Point3(intsnapped.x-gridSpacing,intsnapped.y,gridZ)); hitmesh->setVert(3,tmconst * Point3(intsnapped.x + gridSpacing,intsnapped.y,gridZ)); //now register a hit with the osnap manager //possibly screen for proximity to the foreground theman->RecordHit(new OsnapHit(world_snapped, this, INT_SUB, hitmesh)); #else //!GAME_VER // aszabo|sep.15.04|#596889|The gridSpacing spacing shouldn't be zero, but if it is, it can lead to infinite loops DbgAssert(gridSpacing > 0.0f || gridSpacing < 0.0f); if (gridSpacing > 0.0f || gridSpacing < 0.0f) { // Record all hits that fall in the snap preview area. // Grids are infinite, so we can't loop through their "vertexes". // Instead go through only those that are potential snap points, by starting // at the closest grid point to the mouse and extending in all directions // using "grid size" steps. Point3 intsnapped = Point3(GridCoord(local_cp.x,gridSpacing),GridCoord(local_cp.y,gridSpacing),gridZ); Point3 curIntsnapped(intsnapped); world_snapped = tmconst * intsnapped; // set the window transform to identity to guarantee a world-screen transformation. if (theman->GetVpt() && theman->GetVpt()->getGW()) { theman->GetVpt()->getGW()->setTransform(Matrix3(TRUE)); } // Find all snap points on the right side (positive x) of the intsnapped, including the intsnapped while (CheckPotentialHit(&world_snapped,0, fp)) { got_one = TRUE; RecordNewIntSubHit(world_snapped, tmconst, curIntsnapped, gridSpacing); //ktong|Jan.27.2006|#748560|Limit the number of snap points to search only visibly distinct points. // If the grid point is too far away to tell it from the next gridpoint, stop searching. // No point in enumerating snap points a user can't visibly tell apart. // Check after the first snap point (the closest) is registered to at least have one. if (TooDistant(theman, world_snapped, gridSpacing)) { break; } // Go down the vertical grid line curIntsnapped.y -= gridSpacing; FindVerticalIntSubHit(tmconst, curIntsnapped, fp, (-gridSpacing)); // Go up the vertical grid line curIntsnapped.y = intsnapped.y + gridSpacing; FindVerticalIntSubHit(tmconst, curIntsnapped, fp, gridSpacing); // Go to the right of the original vertival grid line curIntsnapped.y = intsnapped.y; curIntsnapped.x += gridSpacing; world_snapped = tmconst * curIntsnapped; } // Find all snap points on the left side (negative x) of the intsnapped curIntsnapped.y = intsnapped.y; curIntsnapped.x = intsnapped.x - gridSpacing; world_snapped = tmconst * curIntsnapped; //ktong|Jan.27.2006|#748560|Limit the number of snap points to search only visibly distinct points. while (CheckPotentialHit(&world_snapped,0, fp) && !TooDistant(theman, world_snapped, gridSpacing) ) { got_one = TRUE; RecordNewIntSubHit(world_snapped, tmconst, curIntsnapped, gridSpacing); // Go down the vertical grid line curIntsnapped.y -= gridSpacing; FindVerticalIntSubHit(tmconst, curIntsnapped, fp, (-gridSpacing)); // Go up the vertical grid line curIntsnapped.y = intsnapped.y + gridSpacing; FindVerticalIntSubHit(tmconst, curIntsnapped, fp, gridSpacing); // Go to the right of the original vertival grid line curIntsnapped.y = intsnapped.y; curIntsnapped.x -= gridSpacing; world_snapped = tmconst * curIntsnapped; } } #endif //GAME_VER } if( GetActive(EDGE_SUB) && !got_one) { BOOL snapx = FALSE; float xSnap = GridCoord(local_cp.x,gridSpacing); float ySnap = GridCoord(local_cp.y,gridSpacing); float xDist = (float)fabs(xSnap - local_cp.x); float yDist = (float)fabs(ySnap - local_cp.y); Point3 esnapped; // Which one is closer? if(xDist < yDist) { snapx = TRUE; esnapped = Point3(xSnap,local_cp.y,0.0f); } else { esnapped = Point3(local_cp.x,ySnap,0.0f); } world_snapped = tmconst * esnapped;//now in world space if (CheckPotentialHit(&world_snapped,0, fp)) { if(clipgrid(world_snapped, *vpt)) { got_one = TRUE; HitMesh* hitmesh = new HitMesh(3); if(snapx) { hitmesh->setVert(0,tmconst * Point3(esnapped.x,esnapped.y - gridSpacing,0.0f)); hitmesh->setVert(1,tmconst * Point3(esnapped.x,esnapped.y + gridSpacing,0.0f)); } else { hitmesh->setVert(0,tmconst * Point3(esnapped.x - gridSpacing, esnapped.y,0.0f)); hitmesh->setVert(1,tmconst * Point3(esnapped.x + gridSpacing, esnapped.y,0.0f)); } theman->RecordHit(new OsnapHit(world_snapped, this, EDGE_SUB, hitmesh)); } } } }
BOOL TrackMouseCallBack::point_on_obj(ViewExp& vpt, IPoint2 m, Point3& pt, Point3 &norm) { if ( ! vpt.IsAlive() ) { // why are we here DbgAssert(!_T("Invalid viewport!")); return FALSE; } // computes the normal ray at the point of intersection Ray ray, world_ray; float at, best_dist = 0.0f; TimeValue t = MAXScript_time(); Object *obj = NULL; Matrix3 obtm, iobtm; Point3 testNorm; BOOL found_hit = FALSE; vl->face_num_val = vl->face_bary = &undefined; hit_node = NULL; // Calculate a ray from the mouse point vpt.MapScreenToWorldRay(float(m.x), float(m.y), world_ray); for( int i=(nodeTab.Count()-1); i>=0; i-- ) { // Get the object from the node INode* node = nodeTab[i]; ObjectState os = node->EvalWorldState(t); obj = os.obj; // Back transform the ray into object space. obtm = node->GetObjectTM(t); iobtm = Inverse(obtm); ray.p = iobtm * world_ray.p; ray.dir = VectorTransform(iobtm, world_ray.dir); // See if we hit the object if (obj->IsSubClassOf(triObjectClassID)) { TriObject* tobj = (TriObject*)obj; DWORD fi; Point3 bary; if (tobj->mesh.IntersectRay(ray, at, testNorm, fi, bary) && ((!found_hit) || (at<=best_dist)) ) { // Calculate the hit point and transform everything back into world space. // record the face index and bary coord best_dist = at; pt = ray.p + ray.dir * at; pt = pt * obtm; norm = Normalize(VectorTransform(obtm, testNorm)); vl->face_num_val = Integer::intern(fi + 1); vl->face_bary = new Point3Value(bary); hit_node = node; found_hit = TRUE; } } else if (obj->IntersectRay(t, ray, at, testNorm) && ((!found_hit) || (at<=best_dist)) ) { // Calculate the hit point and transform everything back into world space. best_dist = at; pt = ray.p + ray.dir * at; pt = pt * obtm; norm = Normalize(VectorTransform(obtm, testNorm)); hit_node = node; found_hit = TRUE; } } if( found_hit ) return TRUE; // Failed to find a hit on any node, look at the Normal Align Vector for the first node if ((obj!=NULL) && obj->NormalAlignVector(t, pt, testNorm)) // See if a default NA vector is provided { pt = pt * obtm; norm = Normalize(VectorTransform(obtm, testNorm)); return TRUE; } else return FALSE; }