Notifications
Clear all

[Closed] Projecting a Plane on a Sphere

Hi guys i need a quick solution for this (math?) problem i’m facing.
The basic setup is as following: I have a Sphere which represents the earth on this i want to place a plane with a higher resolution texture of the region. My main problem right now is correctly placing the plane. I have two positions on the sphere which corresponds to the bottom left vertex of the plane and the top right vertex, these are quite easy to position But I can’t figure out how to get the other 2 vertex positions. My solution so far was to rotate my two helper objects around their midpoint and use these copies as the remaining positions but this isn’t correct as the plane doesn’t get distorted as it should be. Basically it doesn’t have the curvature of the sphere beneath it. So how do i get the positions/vectors for the other two positions?
More information: the earth is in the center of the world, the two correct coordinates came out from global mapper and this is my third maxscript and the first time i work with vectors/quats.

Another question:
I use the slerp funtion to get the right rotation for the midpoint but when i use this:


  r1 = $point1.rotation
  r2 = $point2.rotation
  rot = slerp r1 r2 [b].5[/b]
  in coordsys local rotate tPoint rot
  in coordsys local move tPoint [0,0,$earth.radius]

i get a point sitting on top of the first point, when i change to

slerp r1 r2 1

i get the midpoint but i want the endpoint point2?!

The picture shows my wrong doing so far. The marked Points are the Positions which are correct. I just need the right math do get the 2 other positions.

3 Replies

this is fairly old and bsaed on intersectray but i still use it for hard surfaces or precise palcement

the ref obj must be an EditMesh

you select the the verts you want to project , and project them
RMB to close
there is no help file , but if it works for your needs … ask what you want


/*
-retopo tool for max 
- written by cyfer 

-this script is meant to help in wraping low res geometry to a higher one 
-the script projects the verts in the 3 main axis (positive & negative) and additional 3 algorithms 
-the most used algorithm is the vert normal , but sometimes the vpt_Cam is really usefull 
-the vpt_Cam shoots a ray from the viewport to the high res geometry(ref) through the low res geometry 
-simply imagine a straight line from the viewport passing through your low res geometry and hits the high res one , this is the direction of projection 


*/


try(destroydialog retopo)catch()
(
global retopo, ref , thesource, pb1,MeshVertArray , i , v

---------------------------------------------------------------------------------------------------------------------------------------------------------------------
fn att thesource ref VertDir =
		(
		global vertSel = polyop.getVertSelection thesource as array
		 for i in VertSel do 
			 (	
				
			 	vertPos = polyop.getVert thesource i 
				DetectRay = Ray VertPos VertDir 
				if (Intersection = IntersectRay ref DetectRay) != undefind do 
							(
							Polyop.SetVert thesource i Intersection.pos 
							
							)
				
				retopo.lbl1.text= "testing_vert " + i as string			
				retopo.lbl1.text= "moving vert ...."	
				retopo.pb1.value = 100.0*i/VertSel.count			
			 )
				retopo.pb1.value = 0
				retopo.lbl1.text= "Ready ! "

		)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------	
 fn Mesh_ops thesource ref VertDir =
 (
	MeshVertArray = getvertselection thesource as array ;
	for v in MeshVertArray do 
		(
			Mvertpos = getVert thesource v
			MV_Norm =  - (getnormal thesource V)	
			raydetect = Ray Mvertpos MV_Norm
			thehit = intersectray ref raydetect
			try(setvert thesource v (thehit.pos))catch()
			
			retopo.lbl1.text= "testing_vert " + v as string
			
			retopo.pb1.value = 100.0*v/MeshVertArray.count
		)
		retopo.pb1.value = 0
		retopo.lbl1.text= "Ready ! "
 )
		
		
---------------------------------------------------------------------------------------------------------------------------------------------------------------------	
 fn sel_Center thesource ref 	 = 
	(
		--gc()
		--clearlistener()
		converttomesh thesource
		
		
		vertarr =  getVertSelection thesource 
		vertselcenter = averageSelVertCenter thesource
		p_center = point pos:(vertselcenter)
		for i in vertarr do --print i
			(
				vertpos = getvert thesource i
				pl = point pos:(vertpos)
				raydetect = Ray vertpos (in coordsys pl (p_center.pos))
				thehit = intersectray ref raydetect
				if thehit != undefined then (setvert thesource i (thehit.pos);retopo.lbl1.text= "moving vert ...."+ thehit.pos as string )
				else (retopo.lbl1.text="NO_HiT !!")
				
				retopo.lbl1.text= "testing_vert ..." +i as string
					
				retopo.pb1.value = 100.0*i/vertarr.count
			)
			--converttopoly thesource
			delete $point*
			retopo.pb1.value = 0
			retopo.lbl1.text= "Ready ! "
	)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
/*
fn vpt_Cam = (
	
	coordSysTM = Inverse(getViewTM())
	viewDir = -coordSysTM.row3
)
*/
---------------------------------------------------------------------------------------------------------------------------------------------------------------------	
rollout retopo "Retopo" width:141 height:372
(
	----------------------------------------------------------------------------------------------
	--Ui Elements
	----------------------------------------------------------------------------------------------
	
	radiobuttons rdo1 "Wrap_Dir" pos:[28,63] width:84 height:158 labels:#("X_Pos", "-X_Pos", "Y_Pos", "-Y_Pos", "Z_Pos", "-Z_Pos", "Vpt_Cam", "Vert_Norm", "Verts_Center") default:0 columns:1
	button btn1 "Project_Verts" pos:[14,275] width:112 height:26
	progressBar pb1 "ProgressBar" pos:[14,331] width:112 height:12 value:0 color:green
	GroupBox grp1 "" pos:[8,51] width:124 height:208
	GroupBox grp2 "" pos:[6,264] width:126 height:87
	label lbl1 "Null" pos:[7,354] width:123 height:14
	pickbutton btn_ref "Pick Refrence Obj" pos:[9,15] width:122 height:30
	button Clear_Buff "Clear_UnDo" pos:[14,307] width:112 height:20
	
	checkbutton ckb1 "Auto_Project" pos:[14,227] width:112 height:24 highlightColor:(color 255 0 0)
								
			
											
	----------------------------------------------------------------------------------------------
	-- Event Handlers 
	----------------------------------------------------------------------------------------------	
	on ckb1 changed true do (rdo1.state = 0 ; btn1.visible = not btn1.visible)
	----------------------------------------------------------------------------------------------
	
	on rdo1 changed state do
	(
			undo on (	
			thesource = selection[1]
			if ckb1.state == on then (
					
				case rdo1.state of 
											(
													1 : VertDir = [1,0,0]
													2 : VertDir = [-1,0,0]
													3 : VertDir = [0,1,0]
													4 : VertDir = [0,-1,0]
													5 : VertDir = [0,0,1]
													6 : VertDir = [0,0,-1]
													7 : (coordSysTM = Inverse(getViewTM()) ; viewDir = -coordSysTM.row3 ; VertDir = ViewDir) 
													8 : (converttomesh thesource ; VertDir = MV_Norm )
													9 : (converttomesh thesource )
											)
						
				if classof thesource == editable_poly then (att thesource ref VertDir)
					else (if rdo1.state == 8 do (Mesh_ops thesource ref VertDir))	
							if rdo1.state == 9 do (sel_Center thesource ref  )							
							
						converttopoly thesource ; max modify mode ; subobjectlevel = 1
						rdo1.state = 0
												)
				else ()							
											))
	----------------------------------------------------------------------------------------------										
	on btn1 pressed do
	(
				--if thesource == undefined then (messagebox "Please Select Refrence object First !") 
		
				
				max modify mode
				subobjectlevel = 1
				undo on (
										coordSysTM = Inverse(getViewTM())
										viewDir = -coordSysTM.row3
										thesource = selection[1]
										--print viewDir
										
										case rdo1.state of 
										(
												1 : VertDir = [1,0,0]
												2 : VertDir = [-1,0,0]
												3 : VertDir = [0,1,0]
												4 : VertDir = [0,-1,0]
												5 : VertDir = [0,0,1]
												6 : VertDir = [0,0,-1]
												7 : VertDir = ViewDir 
												8 : (converttomesh thesource ; VertDir = MV_Norm)
												9 : (converttomesh thesource )
										)
																	
				
				if classof thesource == editable_poly then (att thesource ref VertDir)
					else (if rdo1.state == 8 do (Mesh_ops thesource ref VertDir))	
							if rdo1.state == 9 do (sel_Center thesource ref)	
	
							)
							converttopoly thesource ; max modify mode ; subobjectlevel = 1
										)
	----------------------------------------------------------------------------------------------									
	on btn_ref picked obj do
	(
		if selection != undefined do
			( 
				btn_ref.text = obj.name 
				Ref = getNodeByName obj.name
			)
	)
	----------------------------------------------------------------------------------------------
	on Clear_Buff pressed do
		(ClearUndoBuffer())
	----------------------------------------------------------------------------------------------
	on retopo rbuttondown screenpos do
		(destroydialog retopo ; for i = 1 to 10 do gc(); clearlistener())-- ;
			
	----------------------------------------------------------------------------------------------
			
)
	
	
createdialog retopo fgcolor:[0,255,0]  style:#(#style_toolwindow)
)

I’m not really sure what you’re trying to do with question one, but look at the shperify modifier. With the pivot at 0,0,0 and the plane out on planet’s surface the you may be able to spherify it into the shape you want. Or you break out your trig functions and position each vertex on the sphere.

For the second question, there’s no such thing as “coordsys local” when referencing an object’s absolute position or rotation (notice that the spinners in the interface are always at 0,0,0 when you’re in local mode). You need to move the point to [radius, 0, 0] and then move it’s pivot to 0,0,0 and then you can do your slerp to rotate it into place.

Thinking on this some more, maybe don’t use a plane. Use a chopped squashed sphere with the same radius as the lower res one and rotate it into place.

Thanks guys. I looked into the solutions so far, but haven’t really found a solution to this problem of mine yet.
The one thing that got me thinking was to actually use a high dense sphere and cut it into the piece i need and then amend it’s rotation. But how do i fix the UVs in such a case so that they got the same projection as a simple plane? Remember i’m fairly new to mxs. And by using a plane i thought i wouldn’t need to deal with UVs.

If its still no clear what i’m trying to achieve i have found this fairly equal “thing” on Pete Drapers site. Especially the second picture shows the result i’m after. Building this system into a composite map like Pete’s version would be the second stage