Пример #1
0
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));
}
Пример #2
0
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;
}
Пример #3
0
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());

}
Пример #4
0
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));
			}
		}
	}
}
Пример #5
0
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;
}