Notifications
Clear all

[Closed] Scripting a Planet and Star

Hey all, I’ve recently been trying to build a planet and star system in max as a way of improving my knowledge of maxscript, and having a bit of fun.

I managed to model 3 objects (a star, planet and moon) which orbit around their correct parent, but when i tried to change the speed at which each rotated to add more realism to the scene, they stopped rotating.

Here’s what i have so far

if (classof $ != ObjectSet) then ( 
	messagebox ("need at least 2 selected objects") 
) else ( --we have at least 2 objects
	for obj_id in 2 to $.count do (
		$[obj_id].parent = $[obj_id-1]
	)
	ang=360.0 / (animationRange.end - animationRange.start)
	animate on (
		$Sphere001 do (
			for keytime in animationRange.start to animationRange.end do (
				at time keytime (
					rotate obj (angleAxis ang[0,0,1])
				)
			)
		)
		$Sphere002 do (
			for keytime in animationRange.start to animationRange.end do (
				at time keytime (
					rotate obj (angleAxis ang[0,0,1])
				)
			)
		)
		$Sphere003 do (
			for keytime in animationRange.start to animationRange.end do (
				at time keytime (
					rotate obj (angleAxis ang[0,0,1])
				)
			)
		)
	)
)

what i tried to do was to triplicate the rotation code, and edit it so that it would effect each of the spheres separately, so i could make the rotations more akin to that of the sun, earth and moon.

…But it didn’t work =/

Could anybody give me a kick in the right direction so i can (hopefully) go on to model a full solar system model

cheers guys
-Designasaur

20 Replies
 em3

Sounded like fun so I whipped this up. You can change the values around to suit your needs. Someone can surely make this way better but I got tired and must now sleep.


fn orbitit n pl p therad =
(
			local c=circle radius:(therad) pos:p.pos steps:16 --the orbit
			local par = point name:("p_" + pl.name) size:3 --the planet/moons parent
			local pc = path_constraint() --the path constraint controller
	
						pc.follow = true --child orientation will follow path normal
						par.position.controller = pc
						pc.path = c --assign the path
						pc.percent = random 1 100 --random position around the orbit
						pl.pos = par.pos --move the planet to the parent
						pl.parent = par --assign the planet parent
						return #(c,par) --return the orbit and the parent
)

fn moonit nm ther o =
(
			local ch = Sphere radius:ther --moon
			local thep = orbitit nm ch o (o.radius+5) --do the orbit thing, return the orbit and parent
			ch.parent = thep[2] --assign the point as the planets  parent
			thep[1].parent =  o --assign the planet as the orbit's parent
)

(
			local thesun = $sphere001 --sun object
			local objs = for i = 1 to 5 collect s = sphere radius:(random 5 11) --create planets
	
						for o = 1 to objs.count do
						(
									local rad= thesun.radius*5 --the orbit size
									local mrad = random 1 5 --the moon radius/orbit
									local nmoons = random 1 5 --number of moons
									orbitit o objs[o] thesun ((rad*o)+mrad) --do the orbit thing
									for n = 1 to nmoons do moonit n (mrad*.1) objs[o] --make moons
									rot = random 1 60 --tilt
									with animate on at time (animationrange.start) objs[o].rotation.controller[3].value = objs[o].rotation.controller[3].value --animate at first frame
									with animate on at time (animationrange.end) in coordsys local rotate objs[o] 3 [0,0,(random 720 1540)] --animate at last frame
						)
)

 em3
  1. Reply to original poster with functional script written specifically for poster

  2. Expect nothing in return

  3. Get nothing in return

…well played karma, well played

em3-

I didnt post it but Ill give ya a big thank you. Its great when you get to see other take on solving a problem. So, you effort is certainly appreciated.

-Michael

 em3

haha thanks Michael! It was fun to try. Though I make a conscious effort not to do it now, I have not replied to a few posts I initiated in my day. I thought karma deserved a little recognition.

here is how i would do it. CA + Transform Script…


OrbitAttribute = attributes OrbitAttribute attribid:#(0x00001967,0x12121200) version:1
(
	fn getNode = 
	(
		owner = custattributes.getowner this
		refs.dependentnodes owner firstonly:on
	)
	parameters params rollout:params
	(
		target type:#node ui:ui_target
		orbit_radius1 type:#float default:100 ui:ui_orbit_radius1 
		orbit_radius2 type:#float default:50 ui:ui_orbit_radius2 
		orbit_speed type:#float default:10 ui:ui_orbit_speed
		orbit_yaw type:#float default:0 ui:ui_orbit_yaw
		orbit_pinch type:#float default:0 ui:ui_orbit_pinch
		orbit_roll type:#float default:0 ui:ui_orbit_roll
		
		on target set val do 
		(
			if isvalidnode val and isvalidnode (node = getNode()) do
			(
				c = node.transform.controller
				if c.VariableExists "target" then c.setNode "target" val else c.addNode "target" val
			)
			notifydependents this partid:#tm
		)

		on orbit_radius1 set val do notifydependents this partid:#tm
		on orbit_radius2 set val do notifydependents this partid:#tm
		on orbit_speed set val do notifydependents this partid:#tm
			
		on orbit_yaw set val do notifydependents this partid:#tm
		on orbit_pinch set val do notifydependents this partid:#tm
		on orbit_roll set val do notifydependents this partid:#tm
	)
	rollout params "Parameters" category:1
	(
		group "Target: "
		(
			pickbutton ui_target "None" autoDisplay:on width:144 align:#left offset:[-4,0]
		)
		group "Orbit: "
		(
			spinner ui_orbit_radius1 "Radius 1: " fieldwidth:54 range:[0,1e9,100] align:#right offset:[4,0]
			spinner ui_orbit_radius2 "Radius 2: " fieldwidth:54 range:[0,1e9,50] align:#right offset:[4,-2]

			spinner ui_orbit_speed "Speed: " fieldwidth:54 range:[0,1e9,10] align:#right offset:[4,4]

			spinner ui_orbit_yaw "Yaw: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,4]
			spinner ui_orbit_pinch "Pinch: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
			spinner ui_orbit_roll "Roll: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
		)
	)
)

delete objects
t = sphere name:"target" pos:[0,0,0] radius:20 wirecolor:yellow
p = sphere name:"planet" pos:[100,0,0] radius:10 wirecolor:green

custattributes.add p OrbitAttribute baseobject:on
(
	c = p.transform.controller = Transform_Script()
	c.addtarget "params" p.baseobject.OrbitAttribute
	p.baseobject.OrbitAttribute.target = t
	
	ss = ""
	ss += "ptm = if (this.VariableExists \"target\") and isvalidnode (target = this.getnode \"target\") then target.transform else (Matrix3 1)
" 
	ss += "tm = transmatrix [params.orbit_radius1*(cos (f*params.orbit_speed)), params.orbit_radius2*(sin (f*params.orbit_speed)), 0]
" 
	ss += "rotate tm (rotateYPRMatrix params.orbit_yaw params.orbit_pinch params.orbit_roll)
" 
	ss += "tm *= ptm
" 
	
	c.setexpression ss
	--format ">> %
" (p.baseobject.OrbitAttribute.getNode())
)
setTrajectoryOn p on
select p

all parameters are animatable as you see…
using this snippet you can Add any other astronomical parameters, multiple targets, or/and real physics formulas as well…

enjoy!

2 Replies
(@lucpet)
Joined: 11 months ago

Posts: 0

The “Speed” setting minimum needs to be set to 3.6 as the orbit seems to be linked to the degrees of rotation. If any of that makes sense.

My only problem now is understanding any of the math in this script lol

(@denist)
Joined: 11 months ago

Posts: 0

i absolutely don’t care about units…

lol I meant that the 3.6 is the same as a rotation of 360 degrees if you set the speed to 3.6. You don’t get a full rotation of the planet around the sun it will only travel 150 degrees if set to 1.5 for example. So it will travel part of the distance around the sun and then jump back to the start of the orbit.
So the speed is tied to the distance around the sun.

2 Replies
(@denist)
Joined: 11 months ago

Posts: 0

did you try to change animation range? or maybe i’m missing something…

(@lucpet)
Joined: 11 months ago

Posts: 0

No you’re not missing anything, my mistake sorry. We’ll blame it on my Oxycontin for my muscle strain shall we

new, better, and more correct:


OrbitAttribute = attributes OrbitAttribute attribid:#(0x00001967,0x12121200) version:1
(
	fn getNode = 
	(
		owner = custattributes.getowner this
		refs.dependentnodes owner firstonly:on
	)
	fn update = notifydependents this partid:#tm
	parameters params rollout:params
	(
		target type:#node ui:ui_target
		orbit_radius1 type:#float default:100 ui:ui_orbit_radius1 
		orbit_radius2 type:#float default:50 ui:ui_orbit_radius2 
		orbit_speed type:#float default:10 ui:ui_orbit_speed
		orbit_yaw type:#float default:0 ui:ui_orbit_yaw
		orbit_pinch type:#float default:0 ui:ui_orbit_pinch
		orbit_roll type:#float default:0 ui:ui_orbit_roll
		
		on target set val do 
		(
			if isvalidnode val and isvalidnode (node = getNode()) do
			(
				c = node.transform.controller
				if c.VariableExists "target" then c.setNode "target" val else c.addNode "target" val
			)
			update()
		)

		on orbit_radius1 set val do update()
		on orbit_radius2 set val do update()
		on orbit_speed set val do update()
			
		on orbit_yaw set val do update()
		on orbit_pinch set val do update()
		on orbit_roll set val do update()
			
		planet_velocity type:#float default:20 ui:ui_planet_velocity
		planet_tiltX type:#float default:0 ui:ui_planet_tiltX
		planet_tiltY type:#float default:0 ui:ui_planet_tiltY

		on planet_velocity set val do update()
		on planet_tiltX set val do update()
		on planet_tiltY set val do update()
	)
	rollout params "Parameters" category:1
	(
		group "Target: "
		(
			pickbutton ui_target "None" autoDisplay:on width:144 align:#left offset:[-4,0]
		)
		group "Orbit: "
		(
			spinner ui_orbit_radius1 "Radius 1: " fieldwidth:54 range:[0,1e9,100] align:#right offset:[4,0]
			spinner ui_orbit_radius2 "Radius 2: " fieldwidth:54 range:[0,1e9,50] align:#right offset:[4,-2]

			spinner ui_orbit_speed "Angular Speed: " fieldwidth:54 range:[-1e9,1e9,10] align:#right offset:[4,4]

			spinner ui_orbit_yaw "Yaw: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,4]
			spinner ui_orbit_pinch "Pinch: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
			spinner ui_orbit_roll "Roll: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
		)
		group "Planet: "
		(
			spinner ui_planet_velocity "Rot. Velocity: " fieldwidth:54 range:[-1e9,1e9,20] align:#right offset:[4,4]

			spinner ui_planet_tiltX "Axis Tilt X: " fieldwidth:54 range:[-1,1,0] scale:0.01 align:#right offset:[4,4]
			spinner ui_planet_tiltY "Axis Tilt Y: " fieldwidth:54 range:[-1,1,0] scale:0.01 align:#right offset:[4,-2]
		)
	)
)

delete objects
t = sphere name:"target" pos:[0,0,0] radius:20 wirecolor:yellow
p = sphere name:"planet" pos:[100,0,0] radius:10 wirecolor:green

custattributes.add p OrbitAttribute baseobject:on
(
	c = p.transform.controller = Transform_Script()
	c.addtarget "params" p.baseobject.OrbitAttribute
	p.baseobject.OrbitAttribute.target = t
	
	ss = ""
	ss += "ptm = if (this.VariableExists \"target\") and isvalidnode (target = this.getnode \"target\") then target.transform else (Matrix3 1)
" 
	ss += "tm = transmatrix [params.orbit_radius1*(cos (f*params.orbit_speed)), params.orbit_radius2*(sin (f*params.orbit_speed)), 0]
" 
	ss += "rotate tm (rotateYPRMatrix params.orbit_yaw params.orbit_pinch params.orbit_roll)
"
	ss += "tm *= ptm
" 
	ss += "otm = matrixfromnormal (normalize (point3 params.planet_tiltX params.planet_tiltY 1))
"
	ss += "otm = prerotateZ otm (f*params.planet_velocity)
"
	ss += "translate (otm as matrix3) tm.pos
"	
	
	c.setexpression ss
	--format ">> %
" (p.baseobject.OrbitAttribute.getNode())
)
setTrajectoryOn p on
select p

some bugs were fixed and the code was cleaned up:


OrbitAttribute = attributes OrbitAttribute attribid:#(0x00001967,0x12121200) version:1
(
	fn getNode = 
	(
		owner = custattributes.getowner this
		refs.dependentnodes owner firstonly:on
	)
	fn update = notifydependents this partid:#tm
	
	local script = 
	(
		script = ""
		script += "ptm = if (this.VariableExists \"target\") and isvalidnode target then target.transform else (Matrix3 1)
" 
		script += "ptm = transmatrix ptm.position
" 
		script += "tm = translate (matrix3 1) [params.orbit_radius1*(cos (f*params.orbit_speed)), params.orbit_radius2*(sin (f*params.orbit_speed)), 0]
" 
		script += "rotate tm (rotateYPRMatrix params.orbit_yaw params.orbit_pinch params.orbit_roll)
"
		script += "tm *= ptm
" 
		script += "otm = matrixfromnormal (normalize (point3 params.planet_tiltX params.planet_tiltY 1))
"
		script += "otm = prerotateZ otm (f*params.planet_velocity)
"
		script += "translate (otm as matrix3) tm.pos
"	
	)

	parameters params rollout:params
	(
		target type:#node ui:ui_target
		orbit_radius1 type:#float default:100 ui:ui_orbit_radius1 
		orbit_radius2 type:#float default:50 ui:ui_orbit_radius2 
		orbit_speed type:#float default:10 ui:ui_orbit_speed
		orbit_yaw type:#float default:0 ui:ui_orbit_yaw
		orbit_pinch type:#float default:0 ui:ui_orbit_pinch
		orbit_roll type:#float default:0 ui:ui_orbit_roll
		
		on target set val do 
		(
			if isvalidnode val and isvalidnode (node = getNode()) do
			(
				c = node.transform.controller
				if c.VariableExists "target" then c.setNode "target" val else c.addNode "target" val
			)
			update()
		)

		on orbit_radius1 set val do update()
		on orbit_radius2 set val do update()
		on orbit_speed set val do update()
			
		on orbit_yaw set val do update()
		on orbit_pinch set val do update()
		on orbit_roll set val do update()
			
		planet_velocity type:#float default:20 ui:ui_planet_velocity
		planet_tiltX type:#float default:0 ui:ui_planet_tiltX
		planet_tiltY type:#float default:0 ui:ui_planet_tiltY

		on planet_velocity set val do update()
		on planet_tiltX set val do update()
		on planet_tiltY set val do update()
	)
	rollout params "Parameters" category:1
	(
		group "Target: "
		(
			pickbutton ui_target "None" autoDisplay:on width:144 align:#left offset:[-4,0]
		)
		group "Orbit: "
		(
			spinner ui_orbit_radius1 "Radius 1: " fieldwidth:54 range:[0,1e9,100] align:#right offset:[4,0]
			spinner ui_orbit_radius2 "Radius 2: " fieldwidth:54 range:[0,1e9,50] align:#right offset:[4,-2]

			spinner ui_orbit_speed "Ang. Speed: " fieldwidth:54 range:[-1e9,1e9,10] align:#right offset:[4,4]

			spinner ui_orbit_yaw "Yaw: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,4]
			spinner ui_orbit_pinch "Pinch: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
			spinner ui_orbit_roll "Roll: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
		)
		group "Planet: "
		(
			spinner ui_planet_velocity "Rot. Velocity: " fieldwidth:54 range:[-1e9,1e9,20] align:#right offset:[4,4]

			spinner ui_planet_tiltX "Axis Tilt X: " fieldwidth:54 range:[-1,1,0] scale:0.01 align:#right offset:[4,4]
			spinner ui_planet_tiltY "Axis Tilt Y: " fieldwidth:54 range:[-1,1,0] scale:0.01 align:#right offset:[4,-2]
		)
	)
)

delete objects
t = sphere name:"target" pos:[0,0,0] radius:20 wirecolor:yellow
p = sphere name:"planet" pos:[100,0,0] radius:10 wirecolor:green
s = sphere name:"satellite" pos:[110,0,0] radius:2 wirecolor:yellow

custattributes.add p OrbitAttribute baseobject:on
(
	attr = p.baseobject.OrbitAttribute
	c = p.transform.controller = Transform_Script()
	c.addtarget "params" attr
	c.addnode "target" t
	attr.target = t
	
	c.setexpression attr.script
)
custattributes.add s OrbitAttribute baseobject:on
(
	attr = s.baseobject.OrbitAttribute
	c = s.transform.controller = Transform_Script()
	c.addtarget "params" attr
	c.addnode "target" p
	attr.target = p
	attr.orbit_speed = 20
	attr.orbit_radius1 = 30
	attr.orbit_radius2 = 30
	attr.orbit_yaw = 90
	
	c.setexpression attr.script
)
setTrajectoryOn p on
setTrajectoryOn s on
select p

2 Replies
 em3
(@em3)
Joined: 11 months ago

Posts: 0

This is awesome. Thank you Denis!

(@denist)
Joined: 11 months ago

Posts: 0

my physics theoretic background is pushing me to make the true physics algorithm but i’m too lazy now to listen it … mass, gravity, angular speed, and “everything else”… any one who wants to play with it is welcome.

Page 1 / 2